【问题标题】:how to fix this Task/CancellationToken issue?如何解决此 Task/CancellationToken 问题?
【发布时间】:2014-12-25 16:40:30
【问题描述】:

我正在运行这段代码;

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var task = DoSomething();
            Task.WaitAny(task);

            Console.WriteLine(task.Result);

            Console.Write("Press any key");
            Console.ReadKey();
        }
        static void WriteLine(string str, params string[] param)
        {
            Console.WriteLine(str, param);
            System.Diagnostics.Debug.WriteLine(str, param);
        }

        async static Task<string> DoSomething()
        {
            int timeout = 20;
            int count = 1;
            CancellationTokenSource cts;
            string output;                
            do
            {
                cts = new CancellationTokenSource(timeout);
                //does also happen with
                //output = await Task<string>.Run(() => test(count, timeout, cts.Token));
                output = await Task<string>.Run(() => test(count, timeout, cts.Token), cts.Token);

                if (cts.IsCancellationRequested)
                {
                    WriteLine(string.Format("Retry. Count value {2}, Test Sleep time {0}, Method timeout {1}", output, timeout, count));
                    timeout += 50;
                    count++;
                }
            } while (cts.IsCancellationRequested);

            return string.Format("Count value {2}, Test Sleep time {0}, Method timeout {1}", output, timeout, count);
        }

        async static Task<string> test(int count, int timeout, CancellationToken ct)
        {
            int sleep = 400 - (count * 5);
            await Task.Run(() => Task.Delay(sleep), ct);

            if (!ct.IsCancellationRequested)
            {
                WriteLine(string.Format("Succeed. Count value {2}, Test Sleep time {0}, Method timeout {1}", sleep, timeout, count)); 
            }
            return sleep.ToString();
        }
    }
}

我得到了这个输出

Retry. Count value 1, Test Sleep time 395, Method timeout 20
Retry. Count value 2, Test Sleep time 390, Method timeout 70
Retry. Count value 3, Test Sleep time 385, Method timeout 120
Retry. Count value 4, Test Sleep time 380, Method timeout 170
Retry. Count value 5, Test Sleep time 375, Method timeout 220
Retry. Count value 6, Test Sleep time 370, Method timeout 270
Retry. Count value 7, Test Sleep time 365, Method timeout 320
Succeed. Count value 8, Test Sleep time 360, Method timeout 370
Retry. Count value 8, Test Sleep time 360, Method timeout 370
Succeed. Count value 9, Test Sleep time 355, Method timeout 420

如何解决Count value 8 的问题?

它应该说成功并停在那里。

【问题讨论】:

  • 仅供参考,我使用 timeout = 50 并且无法在 Xamarin 上重现该问题。
  • 你在test方法中检查CancellationToken,然后它进入取消状态,然后你在DoSomething方法中检查CancellationToken
  • 一个问题,你为什么不用output = await test(count, timeout, cts.Token);

标签: c# task cancellationtokensource


【解决方案1】:

问题是竞争条件,因为在“成功”和“重试”检查期间,IsCancellationRequested 可以从 false 更改为 true。在不了解此代码的实际上下文的情况下,很难提出适当的修复建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 2011-06-28
    • 2020-02-16
    • 2019-10-26
    • 2020-03-12
    相关资源
    最近更新 更多