C# c lock()在第二次尝试锁定时挂起
编辑2-> 看看底部; 在现实世界中,我使用锁在serialPort上使用同步读/写(而不是异步读/写)来保护读/写/配置。我在dbg中看到了一些内部WaitOne调用。不知道是否相关。 当您呼叫时,它将执行以下操作: 在拥有控件底层窗口句柄的线程上执行指定的委托 它这样做的方式是将消息发布到所属线程的消息队列中,并等待该线程处理该消息 因此,Invoke是一个阻塞调用,在调用被调用的委托之前不会返回 现在,代码阻塞的可能原因是您的主GUI线程已经在等待其他事情发生,可能是您的外部程序已经完成 因此,它实际上并不是在处理消息 如果这是原因,那么这里的解决方案是删除GUI线程的阻塞部分。不要坐在那里等待外部程序完成,而是旋转出一个等待它完成的任务,然后在它完成时在主窗体上引发适当的事件。同时,主线程可以自由处理消息、更新文本框等 请注意,这意味着如果启动外部程序是为了响应某个事件,如单击按钮,则可能需要在程序运行时禁用部分用户界面,以避免用户单击按钮两次,启动两次并行执行,这两次执行都将报告给同一文本框C# c lock()在第二次尝试锁定时挂起,c#,multithreading,locking,C#,Multithreading,Locking,编辑2-> 看看底部; 在现实世界中,我使用锁在serialPort上使用同步读/写(而不是异步读/写)来保护读/写/配置。我在dbg中看到了一些内部WaitOne调用。不知道是否相关。 当您呼叫时,它将执行以下操作: 在拥有控件底层窗口句柄的线程上执行指定的委托 它这样做的方式是将消息发布到所属线程的消息队列中,并等待该线程处理该消息 因此,Invoke是一个阻塞调用,在调用被调用的委托之前不会返回 现在,代码阻塞的可能原因是您的主GUI线程已经在等待其他事情发生,可能是您的外部程序已经完成
结论:多线程编程很难 根据您的编辑,其中一个锁块内的串行I/O代码似乎已暂停。如果看不到实际的代码,很难猜测它为什么会被暂停……这段代码对我来说运行得非常完美。@SimonWhitehead-那么它是特定于平台/配置的吗?我用4.0CP的目标框架运行它,但“真正的”是3.5。。。这是我的机器,不是。。对我来说,平台更改似乎没有什么不同。它因调用而挂起,调用会将消息发布到表单的输入队列,然后等待处理该消息。如果拥有表单的线程被阻止,它将不会处理消息。
using System;
namespace LockTester
{
public class Class1
{
object m_lock = null;
bool m_isRunning;
System.Threading.Thread m_thread = null;
public Class1()
{
Console.WriteLine("Class1 ctor");
m_lock = new object();
m_isRunning = false;
}
public void DoSomething(){
Console.WriteLine("DoSomething() Trying to acquire lock");
lock(m_lock){
Console.WriteLine("DoSomething() Acquired lock");
}
Console.WriteLine("DoSomething() Released lock");
}
public void Start(){
Console.WriteLine("start()");
m_isRunning = true;
if (m_thread == null){
m_thread = new System.Threading.Thread(Run);
}
m_thread.Start();
}
public void Stop(){
Console.WriteLine("stop()");
m_isRunning = false;
}
private void Run(){
while (m_isRunning){
Console.WriteLine("Trying to acquire lock");
lock(m_lock){
Console.WriteLine("Acquired lock");
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Released lock");
System.Threading.Thread.Sleep(1000);
}
}
}
}
public class TextBoxStreamWriter : TextWriter
{
TextBox _output = null;
Form _form = null;
object _lock = new object();
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (_output.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
_form.Invoke(d, new object[] { text });
}
else
{
_output.AppendText(text);
}
}
public TextBoxStreamWriter(TextBox output, Form form)
{
_output = output;
_form = form;
}
public override void Write(char value)
{
lock (_lock)
{
base.Write(value);
SetText(value.ToString());
}
}
public override Encoding Encoding
{
get { return System.Text.Encoding.UTF8; }
}
}