C# 为什么此代码挂起“等待TransformBlock.Completion”`
C# 为什么此代码挂起“等待TransformBlock.Completion”`,c#,.net-core,task-parallel-library,tpl-dataflow,C#,.net Core,Task Parallel Library,Tpl Dataflow,上的以下代码块等待加载程序完成 我就是不明白为什么 using System; using System.Linq; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; namespace tests { class Program { static async Task Main(string[] args) { Planner pl = new Planne
上的以下代码块等待加载程序完成代码>
我就是不明白为什么
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
namespace tests {
class Program {
static async Task Main(string[] args) {
Planner pl = new Planner();
Console.WriteLine(await pl.Count());
}
}
public class Planner {
private TransformBlock<int, string[]> loader;
private int _im = 0;
public Planner(int im = 5) {
_im = im;
loader =
new TransformBlock<int, string[]>(
async i => {
Console.WriteLine(i);
await Task.Delay(1000);
return new string[] { i.ToString() };
}
);
}
public async Task<long> Count() {
foreach (int i in Enumerable.Range(1, _im))
loader.Post(i);
//loader.Complete(), same blocking
await loader.Completion;
return -1;
}
}
}
使用系统;
使用System.Linq;
使用System.Threading.Tasks;
使用System.Threading.Tasks.Dataflow;
命名空间测试{
班级计划{
静态异步任务主(字符串[]args){
规划师pl=新规划师();
Console.WriteLine(wait pl.Count());
}
}
公共课程规划师{
专用块装载机;
私有int _im=0;
公共规划师(int im=5){
_im=im;
装载机=
新转换块(
异步i=>{
控制台写入线(i);
等待任务。延迟(1000);
返回新字符串[]{i.ToString()};
}
);
}
公共异步任务计数(){
foreach(可枚举范围(1,_-im)中的int i)
装载机.邮政(i);;
//loader.Complete(),相同的阻塞
等待装载机完成;
返回-1;
}
}
}
这里有两个问题
1)你没有告诉区块你已经完成了发布,因此完成
将永远不会收到信号
您需要先调用loader.Complete()
:
loader.Complete();
await loader.Completion;
2)TransformBlock的输出无处可去,因此该块无法完成。在清除其输出缓冲区之前,块无法达到已完成
状态。如果您不关心输出,请创建ActionBlock。否则,您必须将该块链接到其他对象,如缓冲块
,例如:
var results=new BufferBlock<string[]>();
loader.LinkTo(results);
...
loader.Complete();
await loader.Completion;
var results=new BufferBlock();
loader.LinkTo(结果);
...
loader.Complete();
等待装载机完成;
完成一个块不会传播到其他链接块,除非在链接的选项中设置PropagateCompletion
选项。在这种情况下,虽然没有理由将完成传播到BufferBlock