プロセスを中止したいのですが、中止できません。処理機能でバックグラウンドワーカーを使用しています。
_public void Init()
{
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (bw.CancellationPending == true)
{
e.Cancel = true;
}
else
{
e.Result = abd();
}
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled)
{
lbltext.content="Canceled";
}
else
{
lbltext.content="Completed";
}
}
private void btncan_Click(object sender, RoutedEventArgs e)
{
bw.CancelAsync();
}
private void btnstart_Click(object sender, RoutedEventArgs e)
{
bw.RunWorkerAsync();
}
_
このコードを使用してプロセスを中止することはできません。関数abd()
は処理部分を実行し、結果を返します。
解決策を教えてください。
ありがとう。
bw.CancelAsync()
を呼び出すときは、CancellationPending
フラグをtrue
に設定するだけです。デフォルトではキャンセルされません。保留中のキャンセルは手動で処理する必要があります。ただし、ボタンをクリックすると、次の3つのオプションが考えられるため、コードでそれを行うことはできません。
abd()
メソッドは動作を終了し、キャンセルするものはありませんabd()
は作業を開始し、バックグラウンドワーカーはブロックされます-abd()
の結果を待ってから、実行を続行します-つまり、if-else
ブロックを終了し、RunWorkerCompleted
イベントを発生させます。if-else
ブロックが入る前にボタンをクリックします。 CancellationPending
よりもtrueになり、abd()
は実行を開始しませんキャンセルを使用する場合は、実行時間の長いタスクをループで実行し、各ステップでキャンセルが保留されているかどうかを確認します。
void bw_DoWork(object sender, DoWorkEventArgs e)
{
List<Foo> results = new List<Foo>();
// any loop here - foreach, while
for(int i = 0; i < steps_count; i++)
{
// check status on each step
if (bw.CancellationPending == true)
{
e.Cancel = true;
return; // abort work, if it's cancelled
}
results.Add(abd()); // add part of results
}
e.Result = results; // return all results
}
おそらくDoWork
は、CancelAsync
を呼び出す前に、ドキュメントに記載されているようにe.Cancelled
は間違っている可能性があります。
ドキュメント これを言う
DoWorkイベントハンドラーのコードは、キャンセルリクエストが行われているときに作業を終了する可能性があり、ポーリングループでCancellationPendingがtrueに設定されていない可能性があることに注意してください。この場合、キャンセル要求が行われた場合でも、RunWorkerCompletedイベントハンドラーのSystem.ComponentModel.RunWorkerCompletedEventArgsのキャンセル済みフラグはtrueに設定されません。この状況は競合状態と呼ばれ、マルチスレッドプログラミングで一般的な懸念事項です。
次はどうですか?
While(!bw.CancellationPending)
{
//do some work!
}
e.Cancel = true;
Function abd()
の処理に時間がかかりすぎて、途中で中止したいようです。
_private Thread _backgroundWorkerThread;
public void AbortBackgroundWorker()
{
if(_backgroundWorkerThread != null)
_backgroundWorkerThread.Abort();
}
void DoWork(object sender, DoWorkEventArgs e)
{
try
{
_backgroundWorkerThread = Thread.CurrentThread;
// call abd...
}
catch(ThreadAbortException)
{
// Do your clean up here.
}
}
_
AbortBackgroundWorker()
を_btncan_Click
_イベントに入れます。しかし、これにはコストが伴います。これで、RunWorkerCompletedイベントは機能しなくなります。したがって、catchブロックで処理するか、独自のコードを作成する必要があります。