当Task.IsCancelled设置为true时?

时间:2017-02-10 11:33:25

标签: c# task-parallel-library task cancellationtokensource cancellation-token

什么时候会来 Task.IsCanceled = true;

代码:

            var cts = new CancellationTokenSource();
            string result = "";
            cts.CancelAfter(10000);
            try
            {
                Task t = Task.Run(() =>
                {
                    using (var stream = new WebClient().OpenRead("http://www.rediffmail.com"))
                    {
                        result = "success!";
                    }
                    cts.Token.ThrowIfCancellationRequested();
                }, cts.Token);

                Stopwatch timer = new Stopwatch();
                timer.Start();
                while (timer.IsRunning)
                {
                    if (timer.ElapsedMilliseconds <= 10000)
                    {
                        if (result != ""){                                                                                      
                            timer.Stop();
                           Console.WriteLine(result);
                     }
                    }
                    else
                    {
                        timer.Stop();
                        //cts.Cancel();
                        //cts.Token.ThrowIfCancellationRequested();
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine(t.IsCanceled); // still its appear in false.
            }

我的要求是 - 任务未完成最多10秒,需要取消任务。

所以我正在设置计时器并注意到给定的秒数。未完成的意思是取消任务并显示错误信息。

2 个答案:

答案 0 :(得分:3)

您必须将令牌传递给您的方法。它应该检查令牌并尊重对Cancel()的{​​{1}}的呼叫。

或者你自己做:

CancellationTokenSource

一个完整的例子就是:

Task t = Task.Factory.StartNew(() =>
{
    myResult = method();  // Request processing in parallel

    cts.Token.ThrowIfCancellationRequested(); // React on cancellation 
}, cts.Token);

输出是抛出async Task Main() { var cts = new CancellationTokenSource(); var ct = cts.Token; cts.CancelAfter(500); Task t = null; try { t = Task.Run(() => { Thread.Sleep(1000); ct.ThrowIfCancellationRequested(); }, ct); await t; Console.WriteLine(t.IsCanceled); } catch (OperationCanceledException) { Console.WriteLine(t.IsCanceled); } } ,结果是

  

如果您删除了OperationCanceledException部分,则会显示

  

修改

现在,您已经更新了问题,对此提出了一些意见。首先,由于您使用ct.ThrowIfCancellationRequested();方法,因此您不再需要计时器。其次,您需要CancelAfter您的任务。所以这就是这样的:

await

这应该表明string result = ""; cts.CancelAfter(10000); Task t = null; try { t = Task.Run(() => { using (var stream = new WebClient().OpenRead("http://www.rediffmail.com")) { cts.Token.ThrowIfCancellationRequested(); result = "success!"; } }, cts.Token); await t; } catch (OperationCanceledException) { Console.WriteLine(t.IsCanceled); } t.IsCanceled,但当然只有当true的调用时间超过10秒时才会显示。

答案 1 :(得分:1)

来自文档:

  

在以下任何条件下,任务将在TaskStatus.Canceled状态下完成:

     
      
  1. 在任务开始执行之前,它的CancellationToken被标记为取消。

  2.   
  3. 该任务通过抛出一个具有相同CancellationToken的OperationCanceledException来确认已经发出信号的CancellationToken的取消请求。

  4.   
  5. 该任务通过在CancellationToken上调用ThrowIfCancellationRequested方法来确认已经发出信号的CancellationToken的取消请求。

  6.   

所以基本上你需要在你的任务中抛出一个OperationCanceledException来强制状态,例如在你取消它之后执行cts.Token.ThrowIfCancellationRequested()

但是这种机制的意图有点相反。当用户按下表单上的取消按钮(从任务外部)时,您取消源说,任务只是验证是否在某些保存中取消了取消以取消其代码点。