gpt4 book ai didi

c# - ITargetBlock.Completion.ContinueWith() 的最佳实践

转载 作者:太空狗 更新时间:2023-10-29 22:58:33 27 4
gpt4 key购买 nike

这个问题是关于使用 ContinueWith() 时的最佳实践处理 TPL 数据 block 的完成。

ITargetBlock<TInput>.Completion() 方法允许您使用 ContinueWith() 异步处理数据 block 的完成.

考虑以下控制台应用程序代码,它演示了一个非常基本的用法:

private static void Main()
{
test().Wait();
}

static async Task test()
{
var transform = new TransformBlock<int, double>(i => i/2.0);
var output = new ActionBlock<double>(d => Console.WriteLine(d));

// Warning CS4014 here:
transform.Completion.ContinueWith(continuation => output.Complete());
transform.LinkTo(output);

for (int i = 0; i < 10; ++i)
await transform.SendAsync(i);

transform.Complete();
await output.Completion;
}

代码有一个非常简单的 TransformBlock 它将整数除以 2.0 并将它们变成 double 。转换后的数据由 ActionBlock 处理它只是将值输出到控制台窗口。

输出是:

0
0.5
1
1.5
2
2.5
3
3.5
4
4.5

TransformBlock完成了,我也想完成ActionBlock .这样做很方便:

transform.Completion.ContinueWith(continuation => output.Complete());

这就是问题所在。因为这是在 async 中方法,我忽略了 ContinueWith() 的返回值,我收到一个编译器警告:

warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

显然我不能await按照警告建议的调用 - 如果我这样做,代码会挂断,因为 CompleteWith()任务无法完成,直到 transform.Complete()被称为。

现在我在处理警告本身时没有问题(我可以抑制它或将任务分配给变量,或者使用 .Forget() 任务扩展等等)- 但这是我的问题:

  • 以这种方式处理链接的 DataBlock 完成是否安全?
  • 有没有更好的方法?
  • 这里有什么重要的事情被我忽略了吗?

我想如果我做的不是output.Complete()在延续中,我必须提供异常处理 - 但甚至可能只是调用 output.Complete()充满危险?

最佳答案

虽然您可以自己实现完成传播,但 TPL Dataflow 会使用 DataflowLinkOptions.PropagateCompletion 为您完成:

transform.LinkTo(output, new DataflowLinkOptions {PropagateCompletion = true});

如果您仍然想自己实现它,您可以使用 Task.WhenAll 解决存储任务并在适当的时候等待它的问题:

static async Task test()
{
var transform = new TransformBlock<int, double>(i => i/2.0);
var output = new ActionBlock<double>(d => Console.WriteLine(d));

// Warning CS4014 here:
var continuation = transform.Completion.ContinueWith(_ => output.Complete());
transform.LinkTo(output);

for (int i = 0; i < 10; ++i)
await transform.SendAsync(i);

transform.Complete();
await Task.WhenAll(continuation, output.Completion)
}

这使您能够处理 output.Complete 中的任何异常并移除警告。

关于c# - ITargetBlock<TInput>.Completion.ContinueWith() 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27381582/

27 4 0