有没有办法直接“重启”后台工作人员? 调用CancelAsync()后跟RunWorkerAsync()显然不会这样做,因为他们的名字暗示。
背景资料: 我有一个后台工作者,在我的.net 2.0 Windows窗体应用程序中计算总数。 每当用户修改任何属于此总数的值时,我都想重新启动后台工作程序,以防它运行,以便直接考虑最新值。
答案 0 :(得分:8)
backgriound工作本身并没有做任何改变。
当您调用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;
}
}
答案 1 :(得分:2)
有两种选择,一切都取决于你想要给这只猫涂上白色的方法:
如果您想继续使用BackgroundWorker
,那么您需要尊重已建立的模型,即“进度敏感度”之一。 DoWork
内的内容显然需要始终知道待处理的取消是否到期(即,DoWork
循环中需要进行一定数量的轮询)。 / p>
如果您的计算代码是单片的并且您不想弄乱它,那么请不要使用BackgroundWorker
,而是启动您自己的线程 - 这样您就可以强制杀死它,如果需要的话
答案 2 :(得分:0)
您可以为更改值的控件挂钩change事件处理程序,并在处理程序中执行以下操作:
if(!bgWrkr.IsBusy)
//start worker
else if(!bgWrkr.CancellationPending)
bgWrkr.CancelAsync();
希望它可以帮到你!
答案 3 :(得分:0)
我想让我的请求继续运行,但不再关心结果。我覆盖后台工作者的值(我忙的微调器正在使用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);
}
答案 4 :(得分:0)
该方法可以帮助某人...我创建了一个函数来用一种方法重置backgroundworker。我用它来定期执行任务。
通过创建Task
,可以使用CancelAsync
停止backgroundworker并在Task中重新启动。如OP所述,不执行任务将在取消背景工作之前再次启动它。
唯一的要求是您的代码通过某个循环运行,该循环每隔一段时间(CheckPerMilliseconds
检查一次CancellationPending。
private void ResetBackgroundWorker()
{
backgroundWorker.CancelAsync();
Task taskStart = Task.Run(() =>
{
Thread.Sleep(CheckPerMilliseconds);
backgroundWorker.RunWorkerAsync();
});
}
在后台工作人员内部,我使用了一个for循环来检查CancellationPending。
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);
}
}
}