Ali*_*tad 32 .net c# task-parallel-library cancellationtokensource cancellation-token
好的,我的问题非常简单.为什么这段代码不会抛出TaskCancelledException
?
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationTokenSource(500).Token).Result;
Console.WriteLine(v); // this outputs 10 - instead of throwing error.
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
但这一个有效
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationToken(true).Token).Result;
Console.WriteLine(v); // this one throws
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
Geo*_*voy 20
取消正在运行的任务和计划运行的任务有所不同.
在调用Task.Run方法之后,该任务仅被调度,并且可能尚未执行.
当您使用具有取消支持的Task.Run(...,CancellationToken)重载系列时,将在任务即将运行时检查取消令牌.如果取消令牌此时将IsCancellationRequested设置为true,则抛出TaskCanceledException类型的异常.
如果任务已在运行,则任务负责调用ThrowIfCancellationRequested方法,或者只是抛出OperationCanceledException.
根据MSDN,它只是一种方便的方法:
if(token.IsCancellationRequested)抛出新的OperationCanceledException(token);
不是在这两种情况下使用的不同类型的异常:
catch (TaskCanceledException ex)
{
// Task was canceled before running.
}
catch (OperationCanceledException ex)
{
// Task was canceled while running.
}
Run Code Online (Sandbox Code Playgroud)
还要注意TaskCanceledException
派生自OperationCanceledException
,所以你可以只catch
为该OperationCanceledException
类型有一个子句:
catch (OperationCanceledException ex)
{
if (ex is TaskCanceledException)
// Task was canceled before running.
// Task was canceled while running.
}
Run Code Online (Sandbox Code Playgroud)
Alb*_*ano 19
我想因为你没有ThrowIfCancellationRequested()
从CancellationToken对象调用该方法.以这种方式,你忽略了取消任务的请求.
你应该做这样的事情:
void Main()
{
var ct = new CancellationTokenSource(500).Token;
var v =
Task.Run(() =>
{
Thread.Sleep(1000);
ct.ThrowIfCancellationRequested();
return 10;
}, ct).Result;
Console.WriteLine(v); //now a TaskCanceledException is thrown.
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
代码的第二个变体可以工作,因为您已经初始化Canceled
状态设置为true 的标记.事实上,正如说在这里:
If canceled is true, both CanBeCanceled and IsCancellationRequested will be true
Run Code Online (Sandbox Code Playgroud)
已经请求取消,然后TaskCanceledException
立即抛出异常,而不实际启动任务.
另一种实现是使用带有令牌的 Task.Delay 来代替 Thread.Sleep。
static void Main(string[] args)
{
var task = GetValueWithTimeout(1000);
Console.WriteLine(task.Result);
Console.ReadLine();
}
static async Task<int> GetValueWithTimeout(int milliseconds)
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
cts.CancelAfter(milliseconds);
token.ThrowIfCancellationRequested();
var workerTask = Task.Run(async () =>
{
await Task.Delay(3500, token);
return 10;
}, token);
try
{
return await workerTask;
}
catch (OperationCanceledException )
{
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
36235 次 |
最近记录: |