什么是预期在这种情况下,是,如果用户取消通过点击输入任务,其他任务由 ContinueWith
钩将运行,但它不是这样的,因为每一个 AggregateException
尽管明确的处理在不断抛出 ContinueWith
这显然是没有被执行。
在下面的任何澄清吗?
类节目
{
静态无效的主要(字串[] args)
{
CancellationTokenSource tokensource =新CancellationTokenSource();
的CancellationToken令牌= tokensource.Token;
任务task = Task.Run(()=>
{
而(!token.IsCancellationRequested)
{
Console.Write(*);
Thread.sleep代码(1000);
}
},令牌).ContinueWith((T)=>
{
t.Exception.Handle((E)=>真正的);
Console.WriteLine(您已取消任务);
},TaskContinuationOptions.OnlyOnCanceled);
Console.WriteLine(preSS任意键取消);
到Console.ReadLine();
tokensource.Cancel();
task.Wait();
}
}
解决方案
的CancellationToken
作为一个参数 Task.Run
,它只有一个效果,如果它的取消< STRONG>之前任务开始运行。如果任务已经运行,将不可以取消。
要得到一个任务取消的在它已开始运行,你需要使用 CancellationToken.ThrowIfCancellationRequested
,不是的CancellationToken .IsCancellationRequested
。
如果任务被取消,其异常
属性不持有任何的异常,是空
。
如果一个后续任务并不出于某种原因,这意味着它被取消运行。
任务包含本身+及其所有子任务异常(因此, AggregateException
)。
任务开始运行,因为令牌没有被取消。它将运行,直到令牌被取消。之后它会结束延续的不会运行,因为它只有在preceding取消任务运行,并且它一直没有。当你等待
将抛出任务的 AggregateException
与 TaskCanceledException
因为在继续被取消了(如果你能删除持续异常会消失)。
您需要修复的任务,所以它实际上被取消,并删除(或空检查),异常处理,因为没有什么异常:
VAR任务= Task.Run(新动作(()=&GT;
{
而(真)
{
token.ThrowIfCancellationRequested();
Console.Write(*);
Thread.sleep代码(1000);
}
}),令牌).ContinueWith(
T =&GT; Console.WriteLine(您已取消任务),
TaskContinuationOptions.OnlyOnCanceled);
what's expected in this case, is that if the user cancels the task by hitting enter, the other task hooked by ContinueWith
will run, but it's not the case, as per an AggregateException
keeps thrown despite the explicit handling in the ContinueWith
which is apparently not being executed.
any clarification on the below please?
class Program
{
static void Main(string[] args)
{
CancellationTokenSource tokensource = new CancellationTokenSource();
CancellationToken token = tokensource.Token;
Task task = Task.Run(() =>
{
while (!token.IsCancellationRequested)
{
Console.Write("*");
Thread.Sleep(1000);
}
}, token).ContinueWith((t) =>
{
t.Exception.Handle((e) => true);
Console.WriteLine("You have canceled the task");
}, TaskContinuationOptions.OnlyOnCanceled);
Console.WriteLine("Press any key to cancel");
Console.ReadLine();
tokensource.Cancel();
task.Wait();
}
}
解决方案
CancellationToken
as a parameter for Task.Run
it only has an effect if it's cancelled before the task started running. If the task is already running it will not be canceled.
To get a task canceled after it has started running, you need to use CancellationToken.ThrowIfCancellationRequested
, not CancellationToken.IsCancellationRequested
.
If a task is canceled, its Exception
property doesn't hold any exceptions and is null
.
If a continuation task does not run for some reason, that means it was canceled.
A task contains exceptions from itself + all its child tasks (hence, AggregateException
).
The task starts running, because the token is not canceled. It will run until the token gets canceled. After it will end the continuation will not run because it only runs when the preceding task is canceled, and it hasn't been. When you Wait
the task it will throw an AggregateException
with a TaskCanceledException
because the continuation was canceled (if you would remove that continuation the exception will go away).
You need to fix the task so it would actually be canceled, and remove (or null check) the exception handling because there is no exception:
var task = Task.Run(new Action(() =>
{
while (true)
{
token.ThrowIfCancellationRequested();
Console.Write("*");
Thread.Sleep(1000);
}
}), token).ContinueWith(
t => Console.WriteLine("You have canceled the task"),
TaskContinuationOptions.OnlyOnCanceled);