3

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

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

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

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

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

编辑2:为了清楚起见,我正在寻找一种告诉工作线程它应该停止等待Invoke回调并继续工作的方法。

4

2 回答 2

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());
    }
}
于 2012-05-04T14:21:45.810 回答
0

在调用之前检查表单是否仍然存在Invoke。就像是...

if (form != null && !form.Disposed)
    form.Invoke(form.Refresh());
于 2012-05-04T14:18:12.650 回答