そのため、backgroundworkerを使用して各ページを処理するWebページスクレーパーがあります。また、MVVMライトフレームワークを使用していることにも言及したいと思います。
MainViewModelコンストラクター内で、backgroundworkerを初期化しています。
backgroundWorker = new BackgroundWorker()
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
WebBrowserコントロールのLoadCompletedイベントで、backgroundworkerを起動します。
wb = sender; //sender is the webbrowser control
if (!backgroundWorker.IsBusy)
{
backgroundWorker.RunWorkerAsync();
}
次の2つの方法は、DoWorkとStopWorkです。
private System.Threading.AutoResetEvent _resetEvent = new System.Threading.AutoResetEvent(false);
private object wb;
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wk = sender as BackgroundWorker;
if (wb != null)
{
FetchPage(wb);
if (wk.CancellationPending)
{
MessageBox.Show("Cancellation pending!");
}
_resetEvent.Set();
}
}
private void StopWork(object sender)
{
backgroundWorker.CancelAsync();
_resetEvent.WaitOne();
}
fetchpageメソッドは、webbrowserコントロールのソースコードを取得し、コンテンツの解析を開始します。
FetchPageの内部では、BeginInvokeを使用してUIスレッドを更新しています。
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(
() =>
{ ... }
私の問題:[キャンセル]ボタンを押すと、StopWorkメソッドが呼び出され、backgroundWorkerのcancelプロパティが正しくtrueに設定されますが、アプリは続行されます。私のif(wk.CancellationPending)は常にfalseです。
私がここで何を間違っているのかについて何か考えはありますか?私はオンラインとここStackOverflowでたくさんの例を見ました、そしてそれらはすべて私がすでにしたのと同じことを述べています。
ありがとう。
編集:
Ernosが応答した後、CancellationPendingプロパティをFetchPageメソッドに渡して、別の場所で確認しようとしましたが、処理が停止しませんでした。
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wk = sender as BackgroundWorker;
if (wb != null)
{
FetchPage(wb, wk.CancellationPending);
_resetEvent.Set();
}
}
FetchPageの内部では、BeginInvokeを使用してUIスレッドを更新しています。
private void FetchPage(object sender, bool stopAll)
{
if (stopAll)
{
return;
}
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(
() =>
{ ... }
私が試し、取り組んだことは次のとおりです。
private bool stopAllWork = false;
...
private void StopWork(object sender)
{
stopAllWork = true;
backgroundWorker.CancelAsync();
_resetEvent.WaitOne();
}
そしてDoWorkの内部:
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wk = sender as BackgroundWorker;
if (wb != null)
{
FetchPage(wb, stopAllWork);
_resetEvent.Set();
}
}
さて、この実装のために、私の懸念は、不正なbackgroundWorkersが残っているかどうかです。