C# TPL.Dataflow—在ActionBlock中发生未经处理的异常时防止挂起<;T>;

C# TPL.Dataflow—在ActionBlock中发生未经处理的异常时防止挂起<;T>;,c#,.net,tpl-dataflow,C#,.net,Tpl Dataflow,仅从System.Threading.Tasks.Dataflow开始,不确定我是否了解ActionBlock中未处理异常的正确错误处理技术 我现在所拥有的将导致绞刑: -ActionBlock有未处理的异常,不再处理 -生产商无法完成,因为它超出了BoundedCapacity 下面是我的代码(简化为显示一个消费者) 内部类程序 { 私有静态int_processCounter=0; 内部类MyClass { 公共MyClass(内部id) { 这个.Id=Id; } 内部int Id{get

仅从
System.Threading.Tasks.Dataflow
开始,不确定我是否了解
ActionBlock
中未处理异常的正确错误处理技术

我现在所拥有的将导致绞刑: -
ActionBlock
有未处理的异常,不再处理 -生产商无法完成,因为它超出了
BoundedCapacity

下面是我的代码(简化为显示一个消费者)

内部类程序
{
私有静态int_processCounter=0;
内部类MyClass
{
公共MyClass(内部id)
{
这个.Id=Id;
}
内部int Id{get;set;}
}
私有静态void Main(字符串[]args)
{
BufferBlock队列=新的BufferBlock(新的DataflowBlockOptions{BoundedCapacity=10,});
动作块消费者=
新动作块(记录=>过程(记录),
新的ExecutionDataflowBlockOptions{BoundedCapacity=1,});
LinkTo(consumer,newdataflowlinkoptions{PropagateCompletion=true,});
任务生产者=生产(队列);
Trace.TraceInformation(“开始等待生产者和消费者…”);

Task.WhenAll(producer,consumer.Completion).Wait();//你可以做很多事情,因为这与你如何构造你的代码有关。最简单的方法可能是对生产者使用
CancellationToken
并首先等待消费者:

private static void Main(string[] args)
{
    // ...

    var cts = new CancellationTokenSource();
    Task producer = Produce(queue, cts.Token);

    Trace.TraceInformation("Starting to wait on producer and consumer...");
    try
    {
        await consumer.Completion;
    }
    catch
    {
        cts.Cancel();
        // handle
    }

    try
    {
        await producer
    }
    catch
    {
        // handle
    }
}

private static async Task Produce(BufferBlock<MyClass> queue, CancellationToken token)
{
    for (int i = 0; i < 20; i++)
    {
        await queue.SendAsync(new MyClass(i), token);
        Trace.TraceInformation("Sending object number {0}", i);
        await Task.Delay(1);
    }
    Trace.TraceInformation("Completing the producer");
    queue.Complete();
}
private static void Main(字符串[]args)
{
// ...
var cts=新的CancellationTokenSource();
任务生产者=生产(队列,cts.Token);
Trace.TraceInformation(“开始等待生产者和消费者…”);
尝试
{
等待消费者。完成;
}
抓住
{
cts.Cancel();
//处理
}
尝试
{
等待制作人
}
抓住
{
//处理
}
}
专用静态异步任务生成(BufferBlock队列、CancellationToken令牌)
{
对于(int i=0;i<20;i++)
{
wait queue.SendAsync(新的MyClass(i),令牌);
Trace.TraceInformation(“发送对象号{0}”,i);
等待任务。延迟(1);
}
Trace.Trace信息(“完成制作人”);
queue.Complete();
}

Thank you@i3arnon。它觉得这是一个解决方案,填补了框架中的一个空白:挂起可能不会立即出现(在愉快的情况下也不会出现),并且必须手动编写额外的编排。谢谢你!@Alexey没有什么真正挂起。你只是在等待一些永远不会发生的事情。你不需要这么做。
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 0
ConsoleApplication5.vshost.exe Information: 0 : Starting to wait on producer and consumer...
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 1
ConsoleApplication5.vshost.exe Information: 0 : Processing object number 0
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 2
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 3
ConsoleApplication5.vshost.exe Information: 0 : Processing object number 1
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 4
ConsoleApplication5.vshost.exe Information: 0 : Processing object number 2
ConsoleApplication5.vshost.exe Information: 0 : Processing object number 3
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 5
ConsoleApplication5.vshost.exe Information: 0 : Processing object number 4
ConsoleApplication5.vshost.exe Information: 0 : About to throw exception for object 4
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 6
A first chance exception of type 'System.ArgumentException' occurred in ConsoleApplication5.exe
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 7
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 8
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 9
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 10
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 11
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 12
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 13
ConsoleApplication5.vshost.exe Information: 0 : Sending object number 14
<never finishes>
private static void Main(string[] args)
{
    // ...

    var cts = new CancellationTokenSource();
    Task producer = Produce(queue, cts.Token);

    Trace.TraceInformation("Starting to wait on producer and consumer...");
    try
    {
        await consumer.Completion;
    }
    catch
    {
        cts.Cancel();
        // handle
    }

    try
    {
        await producer
    }
    catch
    {
        // handle
    }
}

private static async Task Produce(BufferBlock<MyClass> queue, CancellationToken token)
{
    for (int i = 0; i < 20; i++)
    {
        await queue.SendAsync(new MyClass(i), token);
        Trace.TraceInformation("Sending object number {0}", i);
        await Task.Delay(1);
    }
    Trace.TraceInformation("Completing the producer");
    queue.Complete();
}