【发布时间】: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