我正在尝试修补现有GUI中的问题,其中大部分是通过以下粘贴此代码的代码解决的 - > How to wait for a BackgroundWorker to cancel?
private BackgroundWorker worker = new BackgroundWorker();
private AutoResetEvent _resetEvent = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
}
public void Cancel()
{
worker.CancelAsync();
_resetEvent.WaitOne(); // will block until _resetEvent.Set() call made
// IS THERE ANY WAY TO TELL IF THE BACKGROUNDWORKER STOPPED DUE TO e.Cancel here???
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
while(!e.Cancel)
{
// do something
}
_resetEvent.Set(); // signal that worker is done
}
我的问题作为评论添加到取消功能的结尾。有没有办法知道为什么后台工作人员会关闭?
答案 0 :(得分:0)
有很多选择。您可能可以查看CancellationPending
...我不记得在DoWork
处理程序返回时是否重置 - 我对此表示怀疑,但如果确实如此,您最终会在你的等待和处理程序返回。 (我会自己测试一下,但你的问题并没有包含好Minimal, Complete, and Verifiable code example,我也没有给自己制造一个问题。)
另一种方法是使用TaskCompletionSource<T>
而不是AutoResetEvent
,它支持完成/取消语义:
private BackgroundWorker worker = new BackgroundWorker();
private TaskCompletionSource<object> _tcs;
public Form1()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
// Need to reinitialize when you actually start the worker...you
// didn't show that code, so I'm putting it here
_tcs = new TaskCompletionSource<object>();
}
public async Task Cancel()
{
worker.CancelAsync();
try
{
await _tcs.Task;
// you'll be here if the task completed normally
}
catch (TaskCancelledException)
{
// you'll be here if the task was cancelled
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
while(!e.CancellationPending)
{
// do something
}
if (e.CancellationPending)
{
_tcs.SetCanceled();
}
else
{
// if you actually want to return a value, you can set whatever
// value you want here. You can also use the correct type T for
// the TaskCompletionSource<T> declaration.
_tcs.SetResult(null);
}
}
如果您愿意,可以将Cancel()
称为Cancel().Wait()
,但如果您可以在await
使用BackgroundWorker
则更好,这样您就可以避免阻止线程。
更好的是从$data = $collection->aggregate(
array('$match' => array(
'PATIENT_ID' => array(
'$in' => $arrayPatientId
)
)),
array('$group' => array(
'_id' => '$PATIENT_ID',
'massi1' => array(
'$max' => $dnameth_value
)
))
);
切换到Task
和CancellationTokenSource
。然后你等待的东西可以是任务本身,而不是任务的代理。