当BackgroundWorker在传递给DoWork之前完成后,我可以获得DoWorkEventArgs吗?

时间:2016-10-12 14:39:27

标签: c# backgroundworker autoresetevent

我正在尝试修补现有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
}

我的问题作为评论添加到取消功能的结尾。有没有办法知道为什么后台工作人员会关闭?

1 个答案:

答案 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 ) )) ); 切换到TaskCancellationTokenSource。然后你等待的东西可以是任务本身,而不是任务的代理。