【问题标题】:Task.WhenAll doesn't resumeTask.WhenAll 没有恢复
【发布时间】:2016-02-14 09:46:49
【问题描述】:

下面的代码是我想要做的简化版本。代码应该很快到达 Console.ReadKey() 行,但它永远不会发生。 Task.WhenAll 永远不会恢复下一行。代码有什么问题?

class Program
{
    static void Main(string[] args)
    {
        DoWorkAsync().Wait();
        Console.ReadKey();
    }

    static async Task DoWorkAsync()
    {
        var block = new ActionBlock<Job>(async (task) =>
        {
            await task.DoAsync();
        });
        var jobs = Enumerable.Range(0, 2).Select(i => new Job());
        foreach (var job in jobs)
        {
            await block.SendAsync(job);
        }
        await Task.WhenAll(jobs.Select(c => c.Completion));
    }

    public class Job
    {
        TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>();
        public Task<bool> Completion { get { return completionSource.Task; } }
        public async Task DoAsync()
        {
            await Task.Delay(100);
            completionSource.SetResult(true);
        }
    }

【问题讨论】:

    标签: c# async-await task tpl-dataflow


    【解决方案1】:

    会有帮助的。

    var jobs = Enumerable.Range(0, 2).Select(i => new Job()).ToList();
    

    这是因为jobs的多次枚举

    在这一行await Task.WhenAll(jobs.Select(c =&gt; c.Completion)); 中,您正在等待新的作业,这些作业不会发送到块。

    【讨论】:

    • 你是对的。我从没想过每次迭代给定 IEnumerable 时我都会得到新项目。出乎我的意料。
    • 很遗憾他们还没有模仿ReSharper的多重枚举警告。它可以保护您免受这种错误的影响。
    猜你喜欢
    • 1970-01-01
    • 2020-06-02
    • 2018-01-27
    • 2016-07-11
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多