C#Background worker:调用Close()时的异常

时间:2013-04-17 09:57:58

标签: c# backgroundworker exit

我的应用程序中有两个后台工作程序,用于填充表并发送日志消息。它们使用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
        }
    }

进度已更改的委托将数据/日志插入到用户可见的组件中。

现在,问题是当我点击我的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()表单,这意味着表单处于正确的状态。 更重要的是,如果我检查e.Cancelled函数中的worker_completed标志,我认为它是假的......

在执行Close()函数之前,我该怎么做才能确保在处理RunWorkerCompleted? (或者更确切地说,根本没有处理,因为我们已经放弃了。)

1 个答案:

答案 0 :(得分:0)

我认为您可以在调用ReportProgress之前检查属性Cancellation Pending。

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