我有一个简单的控制台应用程序
<?php echo Html::img('../../uploads/ring.jpg',['class' => 'img-center', 'width'=>150, 'heigth'=>150, 'alt'=>'no image']) ?>
我试图开始新的任务,并在一段时间后取消它。有没有其他方法来实现此结果而不是使用此
class Program
{
private static void MyTask(object obj)
{
var cancellationToken = (CancellationToken) obj;
if(cancellationToken.IsCancellationRequested)
cancellationToken.ThrowIfCancellationRequested();
Console.WriteLine("MyTask() started");
for (var i = 0; i < 10; i++)
{
try
{
if (cancellationToken.IsCancellationRequested)
cancellationToken.ThrowIfCancellationRequested();
}
catch (Exception ex)
{
return;
}
Console.WriteLine($"Counter in MyTask() = {i}");
Thread.Sleep(500);
}
Console.WriteLine("MyTask() finished");
}
static void Main(string[] args)
{
var cancelationTokenSource = new CancellationTokenSource();
var task = Task.Factory.StartNew(MyTask, cancelationTokenSource.Token,
cancelationTokenSource.Token);
Thread.Sleep(3000);
try
{
cancelationTokenSource.Cancel();
task.Wait();
}
catch (Exception ex)
{
if(task.IsCanceled)
Console.WriteLine("Task has been cancelled");
Console.WriteLine(ex.Message);
}
finally
{
cancelationTokenSource.Dispose();
task.Dispose();
}
Console.WriteLine("Main finished");
Console.ReadLine();
}
}
答案 0 :(得分:1)
在这种特定情况下,您可以避免使用.ThrowIfCancellationRequested()
,而只需使用break
来停止执行循环,然后完成Task
。 ThrowIfCancellationRequested
在更深层次的任务树中更有用,其中有更多的后代,并且更难以保持取消。
if (cancellationToken.IsCancellationRequested)
{
break;
}
斯蒂芬·图布(Stephen Toub)有一个good explanation关于如何投掷OCE更像是一种承认。
如果任务的主体也在监视取消令牌并抛出包含该令牌的
OperationCanceledException
(这是ThrowIfCancellationRequested
所做的),那么当任务看到OCE时,它会检查是否OCE的令牌与任务的令牌匹配。如果是,则该异常被视为对合作取消的确认,并且任务转换为已取消状态(而不是故障状态)。
答案 1 :(得分:0)
不确定您对每次迭代检查的异议是什么,但如果您不想检查每次迭代,无论出于何种原因,请检查i
的值:
E.g。这会检查每个第10个循环:
if (i % 10 == 0 && cancellationToken.IsCancellationRequested)
您必须检查的原因是,您可以决定最好停止任务的位置,以便工作不会处于不一致状态。虽然通过不频繁检查可以实现的所有目标都是取消速度较慢的任务,但这可能会导致用户体验的响应速度降低。例如。任务将在500毫秒之前结束,现在它可能需要10倍,5秒。
但是,如果每个循环非常快,并且每个循环检查标志证明显着增加了任务所花费的总时间,那么检查每个n
循环就会产生。