gre*_*van 5 .net c# multithreading task-parallel-library
我有线程任务,它在循环中执行一些操作:
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");
}
Run Code Online (Sandbox Code Playgroud)
我启动它然后在一段时间后取消:
var cts = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => TaskAction(cts.Token), cts.Token);
Thread.Sleep(1000);
cts.Cancel();
Run Code Online (Sandbox Code Playgroud)
这个操作必须正确完成,我不想打断它.但是我想向我的任务发送取消请求并等到它正确完成(我的意思是它在代码中得到了某些点).我尝试了以下方法:
try
{
task.Wait(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
// Must be joined here.
Run Code Online (Sandbox Code Playgroud)
在这种情况下,程序立即返回Wait().任务继续运行,ThrowIfCancellationRequested()但如果主线程退出任务也会中断.
try
{
task.Wait();
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Run Code Online (Sandbox Code Playgroud)
这里主线程等待完成,但最后AggregateException是InnerException= TaskCancelledException(不OperationCancelledException).
static void TaskAction(CancellationToken ct)
{
while (SomeCondition())
{
DoSomeSeriousJob();
if (ct.IsCancellationRequested)
break;
}
}
// ...
task.Wait();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,没有异常上升,但任务RanToCompletion最终获得状态.当SomeCodition()开始返回false 时,这不能从正确完成中解除.
所有这些问题都有简单的解决方法,但我想知道,可能是我错过了什么?谁有人建议我更好的解决方案?
如果您想等待任务同步完成(或取消),您可以尝试这样做:
cts.Cancel();
Task.Run(async () => {
try {
await task;
}
catch (OperationCanceledException ex) {
// ...
}
).Wait();
Run Code Online (Sandbox Code Playgroud)
这样您就可以直接捕获OperationCanceledException而不是捕获AggregateException.
编辑:
等待(CanecllationToken)
这种方法不适用于此目的. MSDN声明:
等待任务完成执行.如果在任务完成之前取消取消令牌,则等待终止.
等待()
您可以使用此方法,但正如您所看到的,您应该期望AggregateException而不是OperationCanceledException.它也在该方法的文件中规定.
AggregateException.InnerExceptions集合包含TaskCanceledException对象.
因此,在这种方法中,为了确保取消操作,您可以检查内部预期是否包含TaskCanceledException.
检查IsCancellationRequested()并没有异常
通过这种方式,很明显没有抛出任何异常,也无法确定操作是否被取消.
如果您不想同步等待,一切都按预期工作:
cts.Cancel();
try {
await task;
}
catch (OperationCanceledException ex) {
// ...
}
Run Code Online (Sandbox Code Playgroud)