在我的应用程序中,我创建了一个绘制Bitmap
对象的线程,当它完成绘制时,调用form.Invoke(form.Refresh)
将位图绘制到主窗体。 (form
是对我申请表的主要形式的引用。)
问题:我注意到如果我关闭表单,而另一个线程正在等待来自UI线程的回调消息(因为Invoke
调用) - 该线程将无限期地等待(?)并且基本上会卡住,阻止应用程序关闭。
使用BeginInvoke
在我的程序中没有意义,因为刷新表单所需的时间必须在线程的工作中考虑。
问:防止这种情况发生的最佳方法是什么?
编辑:我在某些地方读到这是一个坏主意,但在我看来,解决这个问题的唯一方法就是致电Thread.Abort()
。我不能通过使用标志或类似的东西来关闭线程,因为它只是停留在Invoke
调用。
编辑2:为了说清楚,我正在寻找的方法是告诉工作线程它应该停止等待Invoke
回调并继续工作。< / p>
答案 0 :(得分:2)
最好的答案当然是使用BeginInvoke。如果您需要线程等待UI线程处理结果,那么您将不得不向该进程添加另一个同步方法。
AutoResetEvent可用作门,如下所示:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
public class MainForm : Form
{
protected override void OnLoad(EventArgs e)
{
new Thread(ProcessBitmap) { IsBackground = true }.Start(null);
base.OnLoad(e);
}
void DoneProcessingBitmap(Bitmap bitmap)
{
Trace.WriteLine("Done Processing Bitmap");
uiDoneEvent.Set();
}
AutoResetEvent uiDoneEvent = new AutoResetEvent(false);
volatile bool terminate = false;
void ProcessBitmap(object state)
{
while (!terminate)
{
Bitmap bitmap = (Bitmap)state;
Trace.WriteLine("Processing Bitmap");
Thread.Sleep(5000); // simulate processing
BeginInvoke(new Action<Bitmap>(DoneProcessingBitmap), bitmap);
Trace.WriteLine("Waiting");
uiDoneEvent.WaitOne();
}
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
答案 1 :(得分:0)
在致电Invoke
之前,请检查表单是否仍然存在。有点像...
if (form != null && !form.Disposed)
form.Invoke(form.Refresh());