我有多个线程写入日志表单。无论第一条消息是什么线程都会在运行中创建表单。我对每个表单更新使用MyForm.InvokeRequired
/ .Invoke(…)
,但是代码有时会与状态 .WaitForWaitHandle 中的主线程发生死锁。
根据我的理解 - 可能完全不合适 - 问题是有时工人线程会创建表单。此后,即使随后从UI线程更新表单,.InvokeRequired
也将始终为真。在后一种情况下,UI线程可能正在等待自己?
我希望我可以通过在UI线程本身上创建表单来解决这个问题,但是当 MyForm == null 时,我不知道从哪个控件开始。
注意:后台有一个多线程API,用于接收/发送/处理消息,我需要跟踪这些消息。
简化示例:
public static LogForm MyForm;
public static void AddLogLine(string inText) // is called from multiple threads
{
if (MyForm == null) MyForm = new LogForm();
if (MyForm.InvokeRequired)
MyForm.Invoke(new Action<LogForm, string>(_appendText), MyForm ,inText); // deadlock, UI thread state: .WaitForWaitHandle
else
_appendText(MyForm ,inText);
}
答案 0 :(得分:0)
我建议您阅读有关同步上下文的内容: https://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I
每个表单/ dialog / usercontrol都应该在UI线程上初始化,实现这一目的的一种方法是创建主表单的公共静态引用:
public static Form1 StaticReference;
在构造函数上设置它:
public Form1()
{
StaticReference = this;
}
然后在其他地方编写代码:
public static LogForm MyForm;
public static void AddLogLine(string inText) // is called from multiple threads
{
<namespace>.StaticReference.BeginInvoke((MethodInvoker)delegate
{
if (MyForm == null)
MyForm = new LogForm();
Do whatever you want with MyForm within this block.
});
}
您找到的任何解决方案仍然需要以某种方式通过UI线程来编组调用。