根据我对任务的了解,以下代码应取消当前正在执行的任务,而不会引发异常。我的印象是,任务取消的全部目的是礼貌地“要求”任务停止而不中断线程。
以下程序的输出是:
倾销例外 [OperationCanceledException] 取消并返回最后计算的素数。
倾销例外
[OperationCanceledException]
取消并返回最后计算的素数。
我正在尝试避免取消时的任何异常。我该怎么做?
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; }
您在此行上明确抛出了异常:
cancelToken.ThrowIfCancellationRequested();
如果要正常退出任务,则只需摆脱该行。
通常,人们将其用作一种控制机制,以确保中止当前处理而不会潜在地运行任何额外的代码。同样,ThrowIfCancellationRequested()由于在功能上等同于:
ThrowIfCancellationRequested()
if (token.IsCancellationRequested) throw new OperationCanceledException(token);
使用“ ThrowIfCancellationRequested()任务”时,看起来可能更像这样:
int CalculatePrime(CancellationToken cancelToken, object digits) { try{ while(true){ cancelToken.ThrowIfCancellationRequested(); //Long operation here... } } finally{ //Do some cleanup } }
另外,Task.Wait(CancellationToken)如果令牌被取消,将抛出异常。要使用此方法,您需要将Wait调用包装在一个Try...Catch块中。
Task.Wait(CancellationToken)
Try...Catch
MSDN:如何取消任务