C# 条件匹配时TPL数据流完成管道
我认为这是非常基本的方法,但我还没有找到任何例子。 我有一个生产者和一个消费者,我希望在至少处理x个对象时完成管道。此外,我需要知道收到了哪些对象 我就是这样做的:C# 条件匹配时TPL数据流完成管道,c#,task-parallel-library,pipeline,tpl-dataflow,bufferblock,C#,Task Parallel Library,Pipeline,Tpl Dataflow,Bufferblock,我认为这是非常基本的方法,但我还没有找到任何例子。 我有一个生产者和一个消费者,我希望在至少处理x个对象时完成管道。此外,我需要知道收到了哪些对象 我就是这样做的: public class BlockTester { private static TransformBlock<int, int> _worker; public static async Task StartAsync() { _worker = new TransformB
public class BlockTester
{
private static TransformBlock<int, int> _worker;
public static async Task StartAsync()
{
_worker = new TransformBlock<int, int>(s => s + s);
var buffer = new BufferBlock<int>();
var consumeTask = Consume(buffer);
_worker.LinkTo(buffer, new DataflowLinkOptions{PropagateCompletion = true});
foreach (var value in Enumerable.Range(0,100))
{
_worker.Post(value);
}
_worker.Complete();
await buffer.Completion;
if(buffer.TryReceiveAll(out var received))
{
Console.WriteLine(string.Join(", ", received));
}
}
public static async Task<IReadOnlyCollection<int>> Consume(ISourceBlock<int> buffer)
{
var received = new List<int>();
while (await buffer.OutputAvailableAsync())
{
var current = buffer.Receive();
received.Add(current);
if (current > 25)
{
_worker.Complete();
}
}
return received;
}
}
公共类BlockTester
{
私人静态转换块\u工人;
公共静态异步任务StartAsync()
{
_工人=新的转换块(s=>s+s);
var buffer=new BufferBlock();
var consumertask=consumer(缓冲区);
_LinkTo(缓冲区,新数据流链接选项{PropagateCompletion=true});
foreach(可枚举范围(0100)中的var值)
{
_工人岗位(价值);
}
_worker.Complete();
等待缓冲区。完成;
if(buffer.TryReceiveAll(接收到的输出变量))
{
Console.WriteLine(string.Join(“,”,received));
}
}
公共静态异步任务消耗(ISourceBlock缓冲区)
{
var received=新列表();
while(wait buffer.OutputAvailableAsync())
{
var current=buffer.Receive();
已收到。添加(当前);
如果(当前>25)
{
_worker.Complete();
}
}
收到的报税表;
}
}
我对缓冲区有点困惑。TryReceiveAll。等待consume任务和TryReceiveAll之间有什么区别?为什么TryReceiveAll在我的场景中是假的?我想我实现目标的方法还是有问题。你的
消费方法应该是动作块。无需使用OutputAvailableAsync
或TryRecieveAll
。用ActionBlock
替换BufferBlock
,并在ActionBlock
中进行处理。不清楚为什么您需要TransformBlock
,除非您在这个过程中有多个步骤
public class BlockTester
{
//Could be removed
private static TransformBlock<int, int> _worker;
public static async Task StartAsync()
{
//Could be removed
_worker = new TransformBlock<int, int>(s => s + s);
var processor = new ActionBlock<int>(x => ProcessMessage(x));
_worker.LinkTo(processor, new DataflowLinkOptions { PropagateCompletion = true });
foreach (var value in Enumerable.Range(0, 100))
{
_worker.Post(value);
}
//_worker.Complete();
await processor.Completion;
}
private static int itemsRecieved = 0;
public static void ProcessMessage(int x)
{
Interlocked.Increment(ref itemsRecieved);
if (itemsRecieved > 25) _worker.Complete();
//process the message
//log the message etc.
}
}
公共类BlockTester
{
//可以删除
私人静态转换块\u工人;
公共静态异步任务StartAsync()
{
//可以删除
_工人=新的转换块(s=>s+s);
var processor=newactionblock(x=>ProcessMessage(x));
_LinkTo(处理器,新数据流链接选项{PropagateCompletion=true});
foreach(可枚举范围(0100)中的var值)
{
_工人岗位(价值);
}
//_worker.Complete();
等待处理器完成;
}
私有静态int itemsRecieved=0;
公共静态void ProcessMessage(int x)
{
联锁增量(参考项目已确认);
如果(项目确认>25)u worker.Complete();
//处理消息
//记录消息等。
}
}
或使用复杂的消息对象:
public class Message { }
public class BlockTester
{
//Could be removed
private static TransformBlock<Message, Message> _worker;
public static async Task StartAsync()
{
//Could be removed
_worker = new TransformBlock<Message, Message>(s => s);
var processor = new ActionBlock<Message>(x => ProcessMessage(x));
_worker.LinkTo(processor, new DataflowLinkOptions { PropagateCompletion = true });
foreach (var value in Enumerable.Range(0, 100).Select(_ => new Message()))
{
_worker.Post(value);
}
//_worker.Complete();
await processor.Completion;
}
private static ConcurrentBag<Message> itemsRecieved = new ConcurrentBag<Message>();
public static void ProcessMessage(Message x)
{
itemsRecieved.Add(x);
if (itemsRecieved.Count > 25) _worker.Complete();
//process the message
//log the message etc.
}
}
公共类消息{}
公共类块测试器
{
//可以删除
私人静态转换块\u工人;
公共静态异步任务StartAsync()
{
//可以删除
_工人=新的转换块(s=>s);
var processor=newactionblock(x=>ProcessMessage(x));
_LinkTo(处理器,新数据流链接选项{PropagateCompletion=true});
foreach(Enumerable.Range(01100)中的var值)。选择(=>newmessage())
{
_工人岗位(价值);
}
//_worker.Complete();
等待处理器完成;
}
私有静态ConcurrentBag itemsRecieved=新ConcurrentBag();
公共静态无效处理消息(消息x)
{
已确认的项目。添加(x);
如果(itemsRecieved.Count>25)u worker.Complete();
//处理消息
//记录消息等。
}
}
编辑
回答原问题:
为什么TryReceiveAll
返回false:
因为在运行TryReceiveAll
时,BufferBlock
已“完成”。对于要完成的块,其输出缓冲区中必须包含0项。Consume
方法是在允许块完成之前将所有项目取出,最后在一个空块上调用TryRecieveAll
。您的Consume
方法应该是ActionBlock
。无需使用OutputAvailableAsync
或TryRecieveAll
。用ActionBlock
替换BufferBlock
,并在ActionBlock
中进行处理。不清楚为什么您需要TransformBlock
,除非您在这个过程中有多个步骤
public class BlockTester
{
//Could be removed
private static TransformBlock<int, int> _worker;
public static async Task StartAsync()
{
//Could be removed
_worker = new TransformBlock<int, int>(s => s + s);
var processor = new ActionBlock<int>(x => ProcessMessage(x));
_worker.LinkTo(processor, new DataflowLinkOptions { PropagateCompletion = true });
foreach (var value in Enumerable.Range(0, 100))
{
_worker.Post(value);
}
//_worker.Complete();
await processor.Completion;
}
private static int itemsRecieved = 0;
public static void ProcessMessage(int x)
{
Interlocked.Increment(ref itemsRecieved);
if (itemsRecieved > 25) _worker.Complete();
//process the message
//log the message etc.
}
}
公共类BlockTester
{
//可以删除
私人静态转换块\u工人;
公共静态异步任务StartAsync()
{
//可以删除
_工人=新的转换块(s=>s+s);
var processor=newactionblock(x=>ProcessMessage(x));
_LinkTo(处理器,新数据流链接选项{PropagateCompletion=true});
foreach(可枚举范围(0100)中的var值)
{
_工人岗位(价值);
}
//_worker.Complete();
等待处理器完成;
}
私有静态int itemsRecieved=0;
公共静态void ProcessMessage(int x)
{
联锁增量(参考项目已确认);
如果(项目确认>25)u worker.Complete();
//处理消息
//记录消息等。
}
}
或使用复杂的消息对象:
public class Message { }
public class BlockTester
{
//Could be removed
private static TransformBlock<Message, Message> _worker;
public static async Task StartAsync()
{
//Could be removed
_worker = new TransformBlock<Message, Message>(s => s);
var processor = new ActionBlock<Message>(x => ProcessMessage(x));
_worker.LinkTo(processor, new DataflowLinkOptions { PropagateCompletion = true });
foreach (var value in Enumerable.Range(0, 100).Select(_ => new Message()))
{
_worker.Post(value);
}
//_worker.Complete();
await processor.Completion;
}
private static ConcurrentBag<Message> itemsRecieved = new ConcurrentBag<Message>();
public static void ProcessMessage(Message x)
{
itemsRecieved.Add(x);
if (itemsRecieved.Count > 25) _worker.Complete();
//process the message
//log the message etc.
}
}
公共类消息{}
公共类块测试器
{
//可以删除
私人静态转换块\u工人;
公共静态异步任务StartAsync()
{
//可以删除
_工人=新的转换块(s=>s);
var processor=newactionblock(x=>ProcessMessage(x));
_LinkTo(处理器,新数据流链接选项{PropagateCompletion=true});
前面