所以我有一个网页抓取工具,它使用 backgroundworker 来处理每个页面。我还想提一下,我正在使用 MVVM 轻框架。
在我的 MainViewModel 构造函数中,我正在初始化后台工作程序:
backgroundWorker = new BackgroundWorker()
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
在 WebBrowser 控件的 LoadCompleted 事件上,我启动了后台工作程序:
wb = sender; //sender is the webbrowser control
if (!backgroundWorker.IsBusy)
{
backgroundWorker.RunWorkerAsync();
}
我接下来的两种方法是 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 上的取消属性被正确设置为 true,但应用程序仍在继续。我的 if (wk.CancellationPending) 总是假的。
知道我在这里做错了什么吗?我在网上和 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 剩余?