5

私はBackgroundWorkerでスレッドを作成し、CancellationPendingはこのように、真であるかどうループに私はすべての時間を確認してください。アプリケーションが無効になっているとき、BackgroundWorkerスレッドはどのくらい閉じていますか?

public MainPage() 
    { 
     InitializeComponent(); 

     bw = new BackgroundWorker(); 
     bw.WorkerReportsProgress = true; 
     bw.WorkerSupportsCancellation = true; 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
    } 

    private void ButtonStart_Click(object sender, RoutedEventArgs e) 
    { 
     if (bw.IsBusy != true) 
     { 
      bw.RunWorkerAsync(); 
     } 
    } 

    private void ButtonCancel_Click(object sender, RoutedEventArgs e) 
    { 
     if (bw.WorkerSupportsCancellation) 
     { 
      bw.CancelAsync(); 
     } 
    } 

    private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 

     for (int i = 1; i <= 100; i++) 
     { 
      Debug.WriteLine("The tread is working"); 
      if (worker.CancellationPending) 
      { 
       e.Cancel = true; 
       bw.CancelAsync(); 
       break; 
      } 
      else 
      { 

       System.Threading.Thread.Sleep(500); 
       worker.ReportProgress(i); 
      } 
     } 
    } 

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      tbProgress.Text = "Canceled"; 
     } 
     else if (e.Error != null) 
     { 
      tbProgress.Text = "Error: " + e.Error.Message; 
     } 
     else 
     { 
      tbProgress.Text = "Done"; 
     } 
    } 

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     tbProgress.Text = e.ProgressPercentage.ToString() + "%"; 
    } 

アプリケーションが非アクティブ化されると、スレッドは、閉鎖されていなかった、それが中止され、例外が発生します。アプリケーションが無効化されたときに、どのくらいのスレッドがBackgroundWorkerにあるか?

+0

試しましたか?それはあなたが必要とすることをしていますか? –

+0

@ liho1eyはい、私はそれを試してみました。私はこれらのコードをアプリケーションレベルではなくxaml.csページに書きます。 –

+0

okですが、あなたは 'CancelAsync()'を呼び出していますか? –

答えて

5

BackgroundWorkerをキャンセル可能に設定しましたか?

var bg= new BackgroundWorker(); 
bg.WorkerSupportsCancellation = true; 

ドキュメントから:

あなたはBackgroundWorkerのキャンセルをサポートしたい場合はtrueにWorkerSupportsCancellationプロパティを設定します。このプロパティがtrueの場合、CancelAsyncメソッドを呼び出してバックグラウンド操作を中断できます。

また、あなたのコードが間違っているように見えるあなたのスレッドコードのCancelAsync()外を呼び出す必要があり、これはあなたがループを終了するために使用することができますCancellationPendingフラグを設定します。

bw変数がどこから来ているのかわからないので、私は100%確信していませんが、 `

+0

私のコードを編集します。 Plzの外観は私の全コードです。そして、私が言ったようにWorkerSupportsCancellationをtrue/ –

+0

に設定しました。あなたのdo_Workメソッドから 'bw.CancelAsync()'という行を削除しました。どの例外を投稿すれば – thumbmunkeys

+0

がどこから削除されるかは、役に立つでしょう。そして、プロジェクトのプロパティでデバッグを有効にすると、例外が発生します。mscorlib.dllで 'System.Threading.ThreadAbortException'型の最初の例外が発生しました システムで 'System.Threading.ThreadAbortException'型の最初のチャンス例外が発生しました。 dll –

2

ワーカーメソッドでCancellationPendingフラグをチェックし、フラグが設定されている場合は正常に終了する必要があります。
ジョブキャンセルの条件は何ですか?キャンセルボタンをクリックしますか?次に、そこにCancelAsync(...)呼び出しを置く必要があります。 ResetEventオブジェクトのようなものを必要としないように、コード内で既にチェックインしているCancellationPendingフラグを設定します。

+0

@ 9S6いいえCancelationPendingの条件はアプリケーション非アクティブ化状態です。私はアプリケーションが爆破されたときにBWを閉じて、アプリケーションが起動されるとスレッドを続行したい。 –

+0

ここで私はCancelationPendingをチェックする必要がありますか? –

+0

あなたのアプリが非アクティブ化されたときにCancelAysnc(...)を呼び出す必要があります。 CancelAsync(...)を呼び出すと、CancellationPendingフラグが設定されます。あなたは既にあなたのワーカーメソッドでそのフラグをチェックしています - そこからCancelAsync(...)への呼び出しを削除してください。 – A9S6

10

アプリが非アクティブになると、メインUIスレッド以外のすべてのスレッドは、アクティブになるとすぐにThreadAbortExceptionをスローします。これは、アプリケーションが自分のやっていることをすばやく止めるための手段として、「設計通りに」あるようです。スレッドはThreadAbortExceptionを捕捉して何をしているのかをラップアップすることができますが、catchブロックの最後でThreadAbortExceptionが自動的に再生成されることに注意してください。 finallyブロック内のコードも実行されます。

ThreadAbortExceptionが発生し、バックグラウンドワーカーを効果的に停止するため、アプリが非アクティブ化されたときにBackgroundWorkerをキャンセルしようとする理由はありません。この問題が発生したときにクリーンアップを行うには、bw_DoWorkでThreadAbortExceptionをキャッチし、実行する必要があることを実行してから、そのスレッドを終了させます。

アクティベーション後に再度起動するには、アプリを初めて実行したときと同じようにバックグラウンドワーカーを再起動する必要があります。

+0

ありがとう。(15文字) –

+0

これは最高の答えです – Calanus

1

私は自分自身の観察に基づいて、上記の回答に1つの明確な点を追加したいと思います。 バックグラウンドスレッドは、インスタンスが保存されているときに非アクティブ化/アクティブ化を継続します。それが実行されたときに、私はまたBackgroundWorkerオブジェクトのハッシュコードをログに記録

private void Application_Activated(object sender, ActivatedEventArgs e) 
{ 
    if (e.IsApplicationInstancePreserved) 
    { 
     Log.write("Activating, instance preserved"); 
     // restart long-running network requests 
     startBackground(); 
    } 
    else // start over again 
    { 
     AppSettings.init(); 
     Log.write("Activating, rehydrating"); 
     startBackground(); 
    } 
} 

は、私はこのように見えたコードを持っていました。私が見たのは、「Activating、instance preserved」メッセージが出るたびに、 BackgroundWorkerが実行されていることです。

これに基づいて、スレッドは無効化時ではなく、トゥームストーン時に中止される可能性が高いと思われますか?

関連する問題