c#后台工作者:当Close()被调用时异常

本文关键字:调用 异常 Close 后台 工作者 | 更新日期: 2023-09-27 18:09:31

我的应用程序中有两个后台工作者,它们填充一个表并发送日志消息。它们使用ReportProgress方法的"userState"传输这些数据。
它们通过:

连接到主线程。
msg_worker.DoWork              += message_worker_task;
msg_worker.ProgressChanged     += msg_worker_ProgressChanged;
msg_worker.RunWorkerCompleted  += worker_completed;
data_worker.DoWork             += data_worker_task;
data_worker.ProgressChanged    += data_worker_ProgressChanged;
data_worker.RunWorkerCompleted += worker_completed;

它们使用在doWork任务结束时设置的两个EventWaitHandle项进行同步:

private void message_worker_task(object sender, DoWorkEventArgs e)
    {
        try
        {
            while( .. ){ 
               // do work
               bw.ReportProgress( 10, new String("my message to append"));
            }
        }
        finally
        {
            e.Result = 0;
            msg_done.Set(); // EventWaitHandle
        }
    }

Progress更改了在用户可见的组件中插入数据/日志的委托。

现在,问题是,当我点击退出按钮在我的UI,我等待这两个线程:

private void wait_threads()
    {
        int timeout = 30000;
        Cursor.Current = Cursors.WaitCursor;
        if (data_worker.IsBusy && !data_worker.CancellationPending)
        {
            data_worker.CancelAsync();
            data_done.WaitOne(timeout);
        }
        if (msg_worker.IsBusy && !msg_worker.CancellationPending)
        {
            msg_worker.CancelAsync();
            msg_done.WaitOne(timeout);
        }
        Cursor.Current = Cursors.Default;
    }

这似乎是工作(我在代码的其他地方使用它),但在这种"退出"的情况下,我有一个异常,说我试图插入数据到日志组件我有。这个组件是由RunWorkerCompleted委托操作的。

点击Quit时执行的代码是这样的:

    private void quit_Click(object sender, EventArgs e)
    {
        wait_threads(); // blocks until threads are finished
        Close();
    }

我想我弄清楚了,在等待线程完成时,他们发送最后一个事件:RunWorkerCompleted。问题是我在Close()的过程中我的形式,这意味着形式不是在一个正确的状态。更重要的是,如果我检查worker_completed函数中的e.Cancelled标志,我认为它为假…

我能做些什么来确保RunWorkerCompleted被处理之前我的Close()函数得到执行?(更确切地说,根本不处理,因为我们正在退出)。

c#后台工作者:当Close()被调用时异常

我想你可以在调用ReportProgress之前检查cancel Pending属性。

while( .. ){ 
    if (!bw.CancellationPending) 
              bw.ReportProgress( 10, new String("my message to append"));
}