2016-10-12 32 views
0

我想在现有的GUI修补问题,其中大部分是由这个答案粘贴下面的代码解决 - >How to wait for a BackgroundWorker to cancel?当BackgroundWorker在传递给DoWork之前完成后,我可以获取DoWorkEventArgs吗?

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

'worker.CancellationPending'? –

回答

0

有很多选择。您可能会检查CancellationPending…我不记得是否当DoWork处理程序返回—时得到重置我怀疑它,但是如果它确实会结束等待和处理程序返回之间的竞争。 (我刚刚测试过自己,但你的问题不包括良好的Minimal, Complete, and Verifiable code example和我没有麻烦自己创建一个。)

另一种方法是,而不是AutoResetEvent,使用TaskCompletionSource<T>,它支持完成/取消的语义:

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转换为TaskCancellationTokenSource更好。那么你等待的东西可以是任务本身,而不是任务的代理。

相关问题