2016-10-12 13 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&hellipをチェックすることができます; DoWorkハンドラが—を返すときにリセットされるかどうかは思い出せませんが、それが疑わしい場合は、あなたの待ち時間とハンドラが戻る間の競争に巻き込まれるでしょう。 (私はちょうどそれを自分自身をテストしてみただろうが、あなたの質問には良いMinimal, Complete, and Verifiable code exampleが含まれていないと私は1つを作成するために、トラブルに自分をしませんでした。)

別の方法ではなく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().Wait()としてCancel()を呼び出すことができますが、スレッドをブロック避けることができますので、あなたが、そこawaitを使用することができればそれも良いでしょう。

BackgroundWorkerからTaskCancellationTokenSourceに切り替えることよりも優れています。次に、あなたが待っていることは、タスクのプロキシではなく、タスクそのものになります。

関連する問題