C# 冻结我的表格
对于Form1.csC# 冻结我的表格,c#,multithreading,textbox,parallel-processing,deadlock,C#,Multithreading,Textbox,Parallel Processing,Deadlock,对于Form1.cs ... delegate void SetTextCallback(string text); ... public void setText(string s) { if (this.textbox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(setText); this.Invoke(d, new object[] { s }); }
...
delegate void SetTextCallback(string text);
...
public void setText(string s)
{
if (this.textbox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(setText);
this.Invoke(d, new object[] { s });
}
else
{
textbox1.AppendText(s + Environment.NewLine);
Application.DoEvents();
}
}
...
private void btn_Click(object sender, eventArgs e)
{
Test t = new Test();
t.run();
}
和Test.cs
...
public void run()
{
Parallel.ForEach(list, test =>
{
DoSomething(test);
Form1.setText(test + "done!");
}
}
...
在我运行程序后,它总是冻结。
我搜索了一下我的问题,发现是因为死锁问题。
如何解决此问题?您是对的,这是一个死锁问题
Parallel.ForEach
阻塞,直到处理完列表中的所有项目,并且您使其在UI线程上运行,因此现在UI线程被阻塞
然后调用Form1.setText(test+“done!”)
和setText
(顺便说一句,s
应该是大写)调用this.Invoke
,它将阻止调用,直到处理完Invoke调用为止。但是,因为我们在Parallel.ForEach
上阻止了UI线程,因此它将永远不会被处理,而您只是死锁了强>
解决这个问题的方法是将并行。ForEach
也调用它自己的线程,这样就不会阻塞UI线程
public void run()
{
Task.Factory.StartNew(() => Parallel.ForEach(list, test =>
{
DoSomething(test);
Form1.setText(test + "done!");
}), TaskCreationOptions.LongRunning);
}
您还可以通过将this.Invoke
更改为this.BeginInvoke
1来提高性能,这样文本更新也不会阻塞。但是,如果您只将BeginInvoke
更改为您的程序,并使保持并行。在UI线程上,ForEach
可能不再死锁,但您的UI仍将冻结并说没有响应
,直到Parallel.ForEach
完成
一,。在其他任何地方,如果您调用BeginXxxxx
,则必须调用EndXxxxx
,但是BeginInvoke
对从Control
派生的类进行调用,并且您不需要调用EndInvokeDoSomething
在哪里,它是否与textBox1
有关请不要在问题标题中添加标记,这是底部标记的用途。哦,实际上我收到错误消息:无法将lambda表达式转换为类型“System.Threading.Tasks.ParallelOptions”,因为它不是委托类型on变量“test”。我该怎么办?已更改},TaskCreationOptions.LongRunning);到}),TaskCreationOptions.LongRunning);