繁体   English   中英

为什么 Task.WhenAny() 没有按预期工作

[英]Why does Task.WhenAny() not working as expected

我正在尝试为可等待任务实现超时模式,如下所述: https://stackoverflow.com/a/11191070

但是,我得到了意想不到的结果。 我编写了一个小型控制台应用程序来演示(这篇文章的底部)。 这些是我得到的场景和结果:

Scenario 1
DelayTask  Thread.Sleep(10000);
ActualTask Thread.Sleep(100);
Invoked with await Task.WhenAny(...
Result: THEN clause invoked  CORRECT

Scenario 2
DelayTask  Thread.Sleep(100);
ActualTask Thread.Sleep(10000);
Invoked with await Task.WhenAny(...
Result: THEN clause invoked  INCORRECT

Scenario 3
DelayTask  Thread.Sleep(10000);
ActualTask Thread.Sleep(100);
Invoked WITHOUT await: Task.WhenAny(...
Result: ELSE clause invoked  INCORRECT

Scenario 4
DelayTask  Thread.Sleep(100);
ActualTask Thread.Sleep(10000);
Invoked WITHOUT await: Task.WhenAny(...
Result: ELSE clause invoked  CORRECT

任何人都可以解释为什么它没有按预期运行。 蒂亚!

   class Program
    {

        static void Main(string[] args)
        {
            Run();
        }

        private static async void   Run()
        {
            var _cancelWorkTokenSource = new CancellationTokenSource();
            var task = ActualTask(_cancelWorkTokenSource.Token);
            var delayTask = DelayTask(_cancelWorkTokenSource.Token);

            if (await Task.WhenAny(task, delayTask) == task)
            {
                Console.WriteLine("Task Succeeded in time."); 
            }
            else
            {
                Console.WriteLine("Task exceeded time limit");
            };

            Console.ReadLine();
        }

        private static async Task DelayTask(CancellationToken cancelToken)
        {
            Thread.Sleep(10000);
        }

        private static async Task ActualTask(CancellationToken cancelToken)
        {
            Thread.Sleep(100);
        }
    }

因为您的虚拟方法实施不正确。 Thread.Sleep更改为await Task.Delay

private static async Task DelayTask(CancellationToken cancelToken)
{
    await Task.Delay(10000);
}

 private static async Task ActualTask(CancellationToken cancelToken)
 {
    await Task.Delay(100);
 }

您的代码中现在发生了什么:

  1. var task = ActualTask(_cancelWorkTokenSource.Token)阻塞当前线程 10000 毫秒并返回完成的任务
  2. 之后var delayTask = DelayTask(_cancelWorkTokenSource.Token); 阻塞当前线程 100 毫秒并返回已完成的任务
  3. await Task.WhenAny(task, delayTask)选择其中的第一个,因为两者都已完成

添加到您的代码Console.WriteLine(task.IsCompleted); Console.WriteLine(delayTask.IsCompleted); 在相应的变量初始化后检查它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM