有没有办法直接“重启”后台工作人员?调用 CancelAsync() 后跟 RunWorkerAsync() 显然不会像他们的名字所暗示的那样做。
背景信息:我有一个后台工作人员,它在我的 .net 2.0 Windows 窗体应用程序中计算总数。每当用户修改属于此总数的任何值时,我想重新启动后台工作程序以防它正在运行,以便直接考虑最新值。
有没有办法直接“重启”后台工作人员?调用 CancelAsync() 后跟 RunWorkerAsync() 显然不会像他们的名字所暗示的那样做。
背景信息:我有一个后台工作人员,它在我的 .net 2.0 Windows 窗体应用程序中计算总数。每当用户修改属于此总数的任何值时,我想重新启动后台工作程序以防它正在运行,以便直接考虑最新值。
背景工作本身不做任何取消。
当您调用bgw.CancelAsync
它时,它会在后台工作人员上设置一个标志,您需要在 DoWork 处理程序中检查自己。
就像是:
bool _restart = false;
private void button1_Click(object sender, EventArgs e)
{
bgw.CancelAsync();
_restart = true;
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 300; i++)
{
if (bgw.CancellationPending)
{
break;
}
//time consuming calculation
}
}
private void bgw_WorkComplete(object sender, eventargs e) //no ide to hand not sure on name/args
{
if (_restart)
{
bgw.RunWorkerAsync();
_restart = false;
}
}
有几种选择,这完全取决于你想如何给这只猫剥皮:
如果你想继续使用BackgroundWorker
,那么你需要尊重已经建立的模型,即“进度敏感性”之一。里面的东西DoWork
显然需要始终知道挂起的取消是否到期(即,需要在DoWork
循环中进行一定数量的轮询)。
如果您的计算代码是单一的并且您不想弄乱它,那么不要使用BackgroundWorker
,而是启动您自己的线程——这样您可以在需要时强行杀死它。
您可以挂钩更改值的控件的更改事件处理程序,并在处理程序中执行以下操作:
if(!bgWrkr.IsBusy)
//start worker
else if(!bgWrkr.CancellationPending)
bgWrkr.CancelAsync();
希望对你有帮助!
我想让我的请求继续运行,但不再关心结果。我覆盖了后台工作人员的值(我忙碌的微调器正在使用 isBusy 标志)。
private void SearchWorkerCreate() {
this.searchWorker = new BackgroundWorker();
this.searchWorker.DoWork += this.SearchWorkerWork;
this.searchWorker.RunWorkerCompleted += this.SearchWorkerFinish;
}
private void SearchWorkerStart(string criteria){
if(this.searchWorker.IsBusy){
this.SearchWorkerCreate();
}
this.searchWorker.RunWorkerAsync(criteria);
this.OnPropertyChanged(() => this.IsBusy);
this.OnPropertyChanged(() => this.IsIdle);
}
可以这种方法帮助某人...我创建了一个函数来以一种方法重置后台工作人员。我将它用于定期执行的任务。
通过创建一个Task
,可以使用 停止后台工作程序CancelAsync
并在任务内重新启动。正如 OP 所描述的,在取消任务之前,不创建任务将再次启动后台工作程序。
唯一的要求是您的代码通过某个循环运行,该循环在每个时间段 ( CheckPerMilliseconds
) 中检查 CancellationPending。
private void ResetBackgroundWorker()
{
backgroundWorker.CancelAsync();
Task taskStart = Task.Run(() =>
{
Thread.Sleep(CheckPerMilliseconds);
backgroundWorker.RunWorkerAsync();
});
}
在 backgroundworker 中,我使用了一个检查 CancellationPending 的 for 循环。
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while(true)
{
if (backgroundWorker.CancellationPending)
{
return;
}
//Do something you want to do periodically.
for (int i = 0; i < minutesToDoTask * 60; i++)
{
if (backgroundWorker.CancellationPending)
{
return;
}
Thread.Sleep(CheckPerMilliseconds);
}
}
}