我有一个线程任务,它在循环中执行某些操作:
static void TaskAction(CancellationToken ct)
{
while (SomeCondition())
{
DoSomeSeriousJob();
ct.ThrowIfCancellationRequested();
}
}
static void DoSomeSeriousJob()
{
Console.WriteLine("Serious job started");
Thread.Sleep(5000);
Console.WriteLine("Serious job done");
}
我开启它,但在一段时间后取消:
var cts = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => TaskAction(cts.Token), cts.Token);
Thread.Sleep(1000);
cts.Cancel();
这个操作必须正确完成,我不想中断它。但是我想发送一个取消请求到我的任务,并且要等待它正确完成(即到达代码中的某个点)。
我尝试了以下方法:
1. Wait(CancellationToken ct)
1. 使用 Wait(CancellationToken ct)
try
{
task.Wait(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
// Must be joined here.
在这种情况下,程序会立即从
Wait()
返回。任务会继续运行,直到执行ThrowIfCancellationRequested()
,但如果主线程退出,任务也会被中断。
2. Wait()
是什么?try
{
task.Wait();
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
这里主线程等待完成,但是最终会抛出 AggregateException
异常,其 InnerException
为 TaskCancelledException
(而非 OperationCancelledException
)。
3. 检查 IsCancellationRequested() 和无异常
static void TaskAction(CancellationToken ct)
{
while (SomeCondition())
{
DoSomeSeriousJob();
if (ct.IsCancellationRequested)
break;
}
}
// ...
task.Wait();
在这种情况下,没有异常被抛出,但任务最终的状态为“RanToCompletion”。当
SomeCondition()
开始返回false时,这与正确完成不可区分。所有这些问题都有简单的解决方法,但我想知道,是不是我漏掉了什么?是否有人能给我更好的建议?
Wait
,那么它将取消等待。如果你想等待任务完成,请不要将令牌传递给Wait
。 - juharrTaskCanceledException
是从OperationCanceledException
派生而来的。如果您使用await
而不是Wait
,那么AggregateException
将被解开,您可以捕获InnerException
。 - Charles MagerWait(ct)
不会等待的话,调用它有什么用? - greatvovanCancellationToken.ThrowIfCancellationRequested
。 - Daniel C. Weber