2016-10-12 49 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更好。那麼你等待的東西可以是任務本身,而不是任務的代理。

相關問題