java 取消任务,取消后台任务

一些非常好的建议,但我不认为它们解决了潜在的问题:取消后台任务 .

不幸的是,当使用 BackgroundWorker 时,终止任务取决于任务本身 . while 循环终止的唯一方法是,如果后台任务检查其 Cancel 属性并从当前进程返回或中断 .

Example Base

例如,考虑一下

private readonly BackgroundWorker worker = new BackgroundWorker ();

public void SomeFormEventForStartingBackgroundTask ()

{

worker.DoWork += BackgroundTask_HotelCalifornia;

worker.WorkerSupportsCancellation = true;

worker.RunWorkerAsync ();

}

// semantically, you want to perform this task for lifetime of

// application, you may even expect that calling CancelAsync

// will out and out abort this method - that is incorrect.

// CancelAsync will only set DoWorkEventArgs.Cancel property

// to true

private void BackgroundTask_HotelCalifornia (object sender, DoWorkEventArgs e)

{

for ( ; ;)

{

// because we never inspect e.Cancel, we can never leave!

}

}

private void App_FormClosing(object sender, FormClosingEventArgs e)

{

// [politely] request termination

worker.CancelAsync();

// [politely] wait until background task terminates

while (worker.IsBusy);

}

这是默认情况下发生的事情 . 现在,也许你的任务不是一个无限循环,也许它只是一个长期运行的任务 . 无论哪种方式,您的主线程将阻止[实际上它正在旋转,但是whatevs]直到任务完成,或者不是视情况而定 .

如果您亲自编写并可以修改任务,那么您有几个选择 .

Example Improvement

例如,这是上述示例的更好实现

private readonly BackgroundWorker worker = new BackgroundWorker ();

// this is used to signal our main Gui thread that background

// task has completed

private readonly AutoResetEvent isWorkerStopped =

new AutoResentEvent (false);

public void SomeFormEventForStartingBackgroundTask ()

{

worker.DoWork += BackgroundTask_HotelCalifornia;

worker.RunWorkerCompleted += BackgroundTask_Completed;

worker.WorkerSupportsCancellation = true;

worker.RunWorkerAsync ();

}

private void BackgroundTask_HotelCalifornia (object sender, DoWorkEventArgs e)

{

// execute until canceled

for ( ; !e.Cancel;)

{

// keep in mind, this task will *block* main

// thread until cancel flag is checked again,

// so if you are, say crunching SETI numbers

// here for instance, you could still be blocking

// a long time. but long time is better than

// forever ;)

}

}

private void BackgroundTask_Completed (

object sender,

RunWorkerCompletedEventArgs e)

{

// ok, our task has stopped, set signal to 'signaled' state

// we are complete!

isStopped.Set ();

}

private void App_FormClosing(object sender, FormClosingEventArgs e)

{

// [politely] request termination

worker.CancelAsync();

// [politely] wait until background task terminates

isStopped.WaitOne ();

}

虽然这样做更好,但它并不是那么好 . 如果您[合理]确保您的后台任务将结束,这可能“足够好” .

但是,我们[通常]想要的是这样的

private void App_FormClosing(object sender, FormClosingEventArgs e)

{

// [politely] request termination

worker.CancelAsync();

// [politely] wait until background task terminates

TimeSpan gracePeriod = TimeSpan.FromMilliseconds(100);

bool isStoppedGracefully = isStopped.WaitOne (gracePeriod);

if (!isStoppedGracefully)

{

// KILL! KILL! KILL!

}

}

唉,我们做不到 . BackgroundWorker 没有暴露任何强行终止手段 . 这是因为它是一个构建在一些隐藏线程管理系统之上的抽象,如果它被强制终止,它可能会使应用程序的其他部分失去稳定性 .

我实现上述目标的唯一方法是管理自己的线程 .

Example Ideal

所以,例如

private Thread worker = null;

// this time, 'Thread' provides all synchronization

// constructs required for main thread to synchronize

// with background task. however, in the interest of

// giving background task a chance to terminate gracefully

// we supply it with this cancel signal

private readonly AutoResetEvent isCanceled = new AutoResentEvent (false);

public void SomeFormEventForStartingBackgroundTask ()

{

worker = new Thread (BackgroundTask_HotelCalifornia);

worker.IsBackground = true;

worker.Name = "Some Background Task"; // always handy to name things!

worker.Start ();

}

private void BackgroundTask_HotelCalifornia ()

{

// inspect cancel signal, no wait period

//

// NOTE: so cheating here a bit, this is an instance variable

// but could as easily be supplied via parameterized thread

// start delegate

for ( ; !isCanceled.WaitOne (0);)

{

}

}

private void App_FormClosing(object sender, FormClosingEventArgs e)

{

// [politely] request termination

isCanceled.Set ();

// [politely] wait until background task terminates

TimeSpan gracePeriod = TimeSpan.FromMilliseconds(100);

bool isStoppedGracefully = worker.Join (gracePeriod);

if (!isStoppedGracefully)

{

// wipe them out, all of them.

worker.Abort ();

}

}

那就是线程管理的一个不错的介绍 .

哪个最适合你?取决于您的申请 . 最好不要晃动船只,并修改当前的实施以确保这一点

您的后台任务检查并尊重 Cancel 属性

你的主线程等待完成,而不是轮询

比较和评估每种方法的优缺点非常重要 .

如果您必须控制并保证终止其他人的任务,那么编写包含上述内容的线程管理系统可能就是您的选择 . 但是你会失去开箱即用的功能,如线程池,进度报告,跨线程数据编组[工作人员那样做,没有?],以及其他一些东西 . 更不用说,"rolling your own"经常容易出错 .

无论如何,希望这有助于:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值