取消任务是抛出异常 [英] Cancelling a Task is throwing an exception
问题描述
从我读过有关的任务,下面的code应该取消当前正在执行的任务,而不抛出异常。我是IM pression下的任务取消的整点是要礼貌地问的任务停止不中断线程。
从以下程序的输出是:
倾销例外
[OperationCanceledException]
消和最后计算的黄金回来了。
块引用>我想取消,以避免任何异常。我怎样才能做到这一点?
无效的主要()
{
VAR的CancellationToken =新CancellationTokenSource(); VAR任务=新任务< INT>(()=> {
返回CalculatePrime(cancellationToken.Token,10000);
},cancellationToken.Token); 尝试
{
task.Start();
Thread.sleep代码(100);
cancellationToken.Cancel();
task.Wait(cancellationToken.Token);
}
赶上(例外五)
{
Console.WriteLine(倾销除外);
e.Dump();
}
}INT CalculatePrime(的CancellationToken cancelToken,目标位)
{
INT因素;
INT lastPrime = 0; INT C =(int)的数字; 对于(INT NUM = 2; NUM c为C; NUM ++)
{
布尔isprime = TRUE;
因数= 0; 如果(cancelToken.IsCancellationRequested)
{
Console.WriteLine(消和最后计算的黄金回来了。);
//cancelToken.ThrowIfCancellationRequested();
返回lastPrime;
} //看看num是整除
的for(int i = 2; I< = NUM / 2;我++)
{
如果((NUM%I)== 0)
{
// num是整除 - 不是素数
isprime = FALSE;
系数= I;
}
} 如果(isprime)
{
lastPrime = NUM;
}
} 返回lastPrime;
}
解决方案您是在这条线明确地抛出一个异常:
cancelToken.ThrowIfCancellationRequested();
如果你想优雅地退出了任务,那么你只需要摆脱线的。
通常人们用这个作为控制机制,以确保当前的处理没有得到潜在运行任何额外的code中止。此外,没有必要打电话时检查取消
ThrowIfCancellationRequested()
,因为它在功能上等同于:如果(token.IsCancellationRequested)
抛出新OperationCanceledException(令牌);在使用
ThrowIfCancellationRequested()
你的任务可能看起来更像是这样的:INT CalculatePrime(的CancellationToken cancelToken,目标位){
尝试{
而(真){
cancelToken.ThrowIfCancellationRequested(); //长工作这里...
}
}
最后{
//做一些清理
}
}此外,
Task.Wait(的CancellationToken)
将如果令牌被取消抛出异常。要使用这个方法,你需要换你等待的呼叫在<$ C $ C>的try ... catch 块。From what I've read about Tasks, the following code should cancel the currently executing task without throwing an exception. I was under the impression that the whole point of task cancellation was to politely "ask" the task to stop without aborting threads.
The output from the following program is:
Dumping exception
[OperationCanceledException]
Cancelling and returning last calculated prime.
I am trying to avoid any exceptions when cancelling. How can I accomplish this?
void Main() { var cancellationToken = new CancellationTokenSource(); var task = new Task<int>(() => { return CalculatePrime(cancellationToken.Token, 10000); }, cancellationToken.Token); try { task.Start(); Thread.Sleep(100); cancellationToken.Cancel(); task.Wait(cancellationToken.Token); } catch (Exception e) { Console.WriteLine("Dumping exception"); e.Dump(); } } int CalculatePrime(CancellationToken cancelToken, object digits) { int factor; int lastPrime = 0; int c = (int)digits; for (int num = 2; num < c; num++) { bool isprime = true; factor = 0; if (cancelToken.IsCancellationRequested) { Console.WriteLine ("Cancelling and returning last calculated prime."); //cancelToken.ThrowIfCancellationRequested(); return lastPrime; } // see if num is evenly divisible for (int i = 2; i <= num/2; i++) { if ((num % i) == 0) { // num is evenly divisible -- not prime isprime = false; factor = i; } } if (isprime) { lastPrime = num; } } return lastPrime; }
解决方案You are explicitly throwing an Exception on this line:
cancelToken.ThrowIfCancellationRequested();
If you want to gracefully exit the task, then you simply need to get rid of that line.
Typically people use this as a control mechanism to ensure the current processing gets aborted without potentially running any extra code. Also, there is no need to check for cancellation when calling
ThrowIfCancellationRequested()
since it is functionally equivalent to:if (token.IsCancellationRequested) throw new OperationCanceledException(token);
When using
ThrowIfCancellationRequested()
your Task might look more like this:int CalculatePrime(CancellationToken cancelToken, object digits) { try{ while(true){ cancelToken.ThrowIfCancellationRequested(); //Long operation here... } } finally{ //Do some cleanup } }
Also,
Task.Wait(CancellationToken)
will throw an exception if the token was cancelled. To use this method, you will need to wrap your Wait call in aTry...Catch
block.这篇关于取消任务是抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!