【问题标题】:C# DataFlow: Wait for all tasks started by ConcurrentExclusiveSchedulerPair to finishC# DataFlow:等待 ConcurrentExclusiveSchedulerPair 启动的所有任务完成
【发布时间】:2019-03-15 14:39:40
【问题描述】:

我有一个要执行的操作列表,可以在用户交互时取消。很简单,但ConcurrentExclusiveSchedulerPair .Completion 永远不会完成。这是一个例子:

static void Main(string[] args)
{
    var taskSchedulerPair = new ConcurrentExclusiveSchedulerPair();
    var cts = new CancellationTokenSource();
    var optiions = new ExecutionDataflowBlockOptions
    {
        TaskScheduler = taskSchedulerPair.ConcurrentScheduler,
        CancellationToken = cts.Token,
        MaxDegreeOfParallelism = 5
    };
    var a1 = new ActionBlock<int>(new Func<int, Task<int>>(Moo), optiions);
    for (var i = 0; i < 20; i++) a1.Post(i);
    Console.WriteLine("Press any key to cancel...");
    Console.ReadKey(false);
    Console.WriteLine("Cancelling...");
    cts.Cancel();
    // taskSchedulerPair.Complete();
    taskSchedulerPair.Completion.Wait();
    // This never prints
    Console.WriteLine("Done.");
    Console.ReadKey(false);
}

public static async Task<int> Moo(int ms)
{
    Console.WriteLine("Starting: " + ms);
    await Task.Delay(4000);
    Console.WriteLine("Ending" + ms);
    return ms + 100;
}

【问题讨论】:

  • 为什么要使用 ConcurrentExclusiveSchedulerPair ?在任何情况下,需要完成的是 action block,而不是调度程序。对于正常终止,您应该调用a1.Complete();,然后调用await a1.Completion;
  • 如果您关注了How to: Specify a Task Scheduler in a Dataflow Block,这仅用于说明目的,是一个有点不幸的选择。无需使用具有输入缓冲区的数据流块来协调读取器和写入器。使用TaskScheduler.FromCurrentSynchronizationContext() 更新 UI 的块更有用
  • @PanagiotisKanavos,你能把这个写成答案吗?它解决了我的问题。

标签: c# asynchronous task-parallel-library tpl-dataflow


【解决方案1】:

来自docs

调用 Complete 是可选的。 仅当您依赖 Completion 属性通知所有处理已完成时才需要

因此,如果您想在Completion 属性上调用Wait,那么您必须在调度程序上调用Complete()。对于数据流块,此行为是相同的;要依赖 Completion 属性,您必须在块上调用 Complete()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 2011-03-17
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多