【问题标题】:Why doesn't my Tasks start running unless I call Task.WhenAll()? [duplicate]除非我调用 Task.WhenAll(),否则为什么我的任务不会开始运行? [复制]
【发布时间】:2021-05-15 09:55:13
【问题描述】:

我有下面的代码。 (忽略FindPhysicalPdfTicketAsync的内部细节,内部包含await/awaitable)

IEnumerable<Task> findPhysicalPdfTicketTasks = irTable.ToList().Select(row =>
{
    return FindPhysicalPdfTicketAsync(row,
        ticketListUserControl.physicalPdfTicketExistsStatus);
});

除非我在上述代码之后的一行中调用Task.WhenAll(findPhysicalPdfTicketTasks)await Task.WhenAll(findPhysicalPdfTicketTasks),否则枚举中的任务永远不会执行。

作为测试,我在枚举之外独立运行了FindPhysicalPdfTicketAsync 方法,并且任务执行良好。

例如

IEnumerable<Task> test = irTable.First();

FindPhysicalPdfTicketAsync(test, ticketListUserControl.physicalPdfTicketExistsStatus);

那么,为什么可枚举的需要Task.WhenAll


更新:我的问题在我发布后续内容之前已经结束:

那么是什么原因导致Task.WhenAll(findPhysicalPdfTicketTasks) 触发枚举呢?我的理解是WhenAll() 所做的只是等待所有“假定已经在运行”的任务完成。

【问题讨论】:

  • Select之后添加ToList和返回语句的结尾,这样你的枚举就实现了。否则它会被懒惰地评估。
  • 因为延迟执行。
  • Select() 仅返回一个投影承诺,在您枚举其结果之前它不会执行其中的表达式。
  • 两件事。 1. 我知道惰性/延迟行为。我正在查看我的代码的 irTable.ToList() 部分,并认为这应该已经引起了枚举。我并没有意识到我需要另一个 .ToList 来“再次”触发 select 语句的枚举。我的错,我错过了。
  • K.Carter Sr. Task.WhenAll 在提供IEnumerable&lt;Task&gt; 参数时,通过枚举它立即实现可枚举,并将实现的任务存储到List&lt;Task&gt;。你可以研究它的源代码here

标签: c# multithreading asynchronous async-await task-parallel-library


【解决方案1】:

LINQ .Select() 创建一个 IEnumerable 对象。但该对象不会执行其主体语句 直到您要求它为您提供结果。

要获得结果并使其执行主体语句,您需要枚举 IEnumerable。这可以通过多种方式完成,例如:

var taskList = findPhysicalPdfTicketTasks.ToList();

var taskArray = findPhysicalPdfTicketTasks.ToArray();

foreach (var task in findPhysicalPdfTicketTasks)
{
    // ...
}

或者(就像你已经做过的那样):

await Task.WhenAll(findPhysicalPdfTicketTasks);

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多