C# 如何根据条件停止TransformBlock处理剩余的排队消息?

C# 如何根据条件停止TransformBlock处理剩余的排队消息?,c#,task,task-parallel-library,tpl-dataflow,C#,Task,Task Parallel Library,Tpl Dataflow,下面是在控制台项目中使用TPL数据流的简单工作流的代码 三个测试对象TestA、TestB和TestC被发布到起始缓冲块中。这链接到一个TransformBlock,该TransformBlock评估每个测试的PerformTestAsync()方法,该方法返回一个任务。TransformBlock链接到ActionBlock,ActionBlock将测试结果写入控制台 所有这些似乎都很有效。但是,我正在努力更改代码,以便第一次等待t.PerformTestAsync()返回TestResult

下面是在控制台项目中使用TPL数据流的简单工作流的代码

三个测试对象TestA、TestB和TestC被发布到起始缓冲块中。这链接到一个TransformBlock,该TransformBlock评估每个测试的
PerformTestAsync()
方法,该方法返回一个
任务。TransformBlock链接到ActionBlock,ActionBlock将测试结果写入控制台

所有这些似乎都很有效。但是,我正在努力更改代码,以便第一次
等待t.PerformTestAsync()
返回
TestResult.Failed
我希望TransformBlock不再处理消息,当然除了失败的结果之外,不会再传递给ActionBlock。因此,对于我的示例代码,我只希望在控制台窗口中看到“OK”和“Failed”,而对于
testC.PerformTestAsync()
,则根本不需要调用

我怎样才能做到这一点

代码:

类程序
{
静态void Main(字符串[]参数)
{
//创建工作流块
var bufferBlock=新的bufferBlock();
var transformBlock=new transformBlock(异步t=>wait t.PerformTestAsync());
var actionBlock=newactionblock(i=>Console.WriteLine(i));
//连接块
LinkTo(transformBlock,新的DataflowLinkOptions(){PropagateCompletion=true});
LinkTo(actionBlock,新的DataflowLinkOptions(){PropagateCompletion=true});
//创建测试
var tests=newlist(){newtesta(),newtestb(),newtestc()};
//将它们发布到工作流的开始
foreach(测试中的var测试)
{
缓冲块后(测试);
}
bufferBlock.Complete();
actionBlock.Completion.Wait();
Console.ReadLine();
}
}
公共枚举测试结果
{
好啊
错误,
失败
}
公共抽象类测试库
{
私有只读字符串\u名称;
公共测试库(字符串名称)
{
_名称=名称;
}
公共抽象任务PerformTestAsync();
}
公共类TestA:TestBase
{
公共TestA():基(“测试A”)
{
}
公共覆盖任务PerformTestAsync()
{
//为这个测试做一些处理。。。
返回Task.FromResult(TestResult.OK);
}
}
公共类TestB:TestBase
{
公共测试B():基本(“测试B”)
{
}
公共覆盖任务PerformTestAsync()
{
//为这个测试做一些处理。。。
返回Task.FromResult(TestResult.Failed);
}
}
公共类TestC:TestBase
{
公共TestC():基(“TestC”)
{
}
公共覆盖任务PerformTestAsync()
{
//为这个测试做一些处理。。。
返回Task.FromResult(TestResult.OK);
}
}

等待t.PerformTestAsync()
返回
TestReuslt.Failed
时,抛出异常。这将导致流出现故障并阻止任何进一步的处理。然后,流将在故障状态下完成。将不再处理其他项目

var transformBlock = new TransformBlock<TestBase, TestResult>(async t =>
{
    var result = await t.PerformTestAsync();
    if (result == TestResult.Failed)
        throw new InvalidOperationException();
    return result;
});
var transformBlock=新transformBlock(异步t=>
{
var结果=等待t.PerformTestAsync();
if(result==TestResult.Failed)
抛出新的InvalidOperationException();
返回结果;
});

请注意,您抛出的异常将传播到最后一个块的
完成
任务,即您的
操作块
。当您等待该任务时,您将能够根据自己的选择处理故障流或忽略

嗨,谢谢你的回复。是的,我知道你所描述的将如何运作。然而,我希望找到一个可能比抛出异常更简单的解决方案。我的场景是可以预见的,因此相应地编写代码比抛出异常感觉更正确,而抛出异常实际上应该留给异常情况。但是,也许这是不可能的情况?还有其他选项,比如为块设置忽略消息的标志,但是如果希望块停止将消息接收到其队列中,则块必须出现故障或取消。因此,您可以将这两种方法结合起来,取消该块以防止接受新消息,并设置一个标志以忽略队列中已有的消息。但是处理异常和重新初始化流可能是更简单的方法。我认为你是对的,异常方法可能只是处理事情的实用方法。再次感谢。
var transformBlock = new TransformBlock<TestBase, TestResult>(async t =>
{
    var result = await t.PerformTestAsync();
    if (result == TestResult.Failed)
        throw new InvalidOperationException();
    return result;
});