我的应用程序中有两个后台工作人员,他们填写表格并发送日志消息。他们使用 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 委托操作。
单击退出时执行的代码是这样的:
private void quit_Click(object sender, EventArgs e)
{
wait_threads(); // blocks until threads are finished
Close();
}
我想我发现在等待线程完成时,它们会发送最后一个事件:RunWorkerCompleted。问题是我正在 Close() 我的表单的过程中,这意味着表单处于不正确的状态。更重要的是,如果我检查函数e.Cancelled
中的标志worker_completed
,我认为它是错误的......
我可以做些什么来确保在我的函数执行之前处理 RunWorkerCompleted?Close()
(或者更确切地说,根本没有处理,因为我们要退出)。