我的应用程序中有两个后台工作程序,用于填充表并发送日志消息。它们使用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? (或者更确切地说,根本没有处理,因为我们已经放弃了。)
答案 0 :(得分:0)
我认为您可以在调用ReportProgress之前检查属性Cancellation Pending。
while( .. ){
if (!bw.CancellationPending)
bw.ReportProgress( 10, new String("my message to append"));
}