防止表单关闭冻结调用调用

时间:2012-05-04 13:52:19

标签: c# winforms

在我的应用程序中,我创建了一个绘制Bitmap对象的线程,当它完成绘制时,调用form.Invoke(form.Refresh)将位图绘制到主窗体。 (form是对我申请表的主要形式的引用。)

问题:我注意到如果我关闭表单,而另一个线程正在等待来自UI线程的回调消息(因为Invoke调用) - 该线程将无限期地等待(?)并且基本上会卡住,阻止应用程序关闭。

使用BeginInvoke在我的程序中没有意义,因为刷新表单所需的时间必须在线程的工作中考虑。

问:防止这种情况发生的最佳方法是什么?

编辑:我在某些地方读到这是一个坏主意,但在我看来,解决这个问题的唯一方法就是致电Thread.Abort()。我不能通过使用标志或类似的东西来关闭线程,因为它只是停留在Invoke调用。

编辑2:为了说清楚,我正在寻找的方法是告诉工作线程它应该停止等待Invoke回调并继续工作。< / p>

2 个答案:

答案 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());