C# 数据流块中的不同消息类型
我需要设计自定义datafloaw块,它的作用类似于缓冲区,但会在超时后使项目可用。我会将传入的消息放入队列并启动计时器。当定时器被触发时,我将把一个项目从队列移动到缓冲块中,这将使它对数据流消费者可用 若我将一个项目从内部队列移动到计时器处理程序的输出缓冲区块中,显然它不会是线程安全的,因为计时器处理程序可能会与队列调用冲突并损坏队列。MSDN中声称数据流基于Actor思想,该思想假设消息是单线程执行的,从而解决了同步问题。但如果我引入一个计时器处理程序,这将打破这个假设。我可以在队列上使用老式锁,也可以使用CuncurrentQueue,但我想知道是否有更特殊的数据流方式来管理计时器,以便它不会与数据流块的Post()调用冲突 或者,为了扩展这个问题,是否有一种优雅的方式让数据流块处理几种不同类型的消息,并且仍然提供线程安全模型?来自: 因为运行时管理数据之间的依赖关系,所以通常可以避免同步访问共享数据的要求 这意味着,当您在代码中使用数据流块时,您通常不必担心同步问题,因为这些块为您完成了同步 但是,当您编写自定义数据流块时,您确实需要自己处理同步。例如,假设您正在实现C# 数据流块中的不同消息类型,c#,task-parallel-library,actor,tpl-dataflow,C#,Task Parallel Library,Actor,Tpl Dataflow,我需要设计自定义datafloaw块,它的作用类似于缓冲区,但会在超时后使项目可用。我会将传入的消息放入队列并启动计时器。当定时器被触发时,我将把一个项目从队列移动到缓冲块中,这将使它对数据流消费者可用 若我将一个项目从内部队列移动到计时器处理程序的输出缓冲区块中,显然它不会是线程安全的,因为计时器处理程序可能会与队列调用冲突并损坏队列。MSDN中声称数据流基于Actor思想,该思想假设消息是单线程执行的,从而解决了同步问题。但如果我引入一个计时器处理程序,这将打破这个假设。我可以在队列上使用老
BufferBlock
。对该块调用Post()
必须以某种方式同步,因为两个源块可以同时调用Post()
。没有人会为您处理同步,因此您的Post()
*实现需要使用锁或ConcurrentQueue
或类似的东西
*实际上,您并没有实现Post()
,而是实现了OfferMessage()
但是,如果我正确理解了您的需求,您实际上可以通过利用TDF中已经存在的同步来实现您的块,而无需任何手动同步。您可以使用两个BufferBlock
s、一个helperTask
和DataflowBlock.enclosure()
来实现您的块:
公共静态IPropagatorBlock CreateDelayedBlock(时间跨度延迟)
{
var source=new BufferBlock();
var target=new BufferBlock();
任务。运行(
异步()=>
{
while(等待source.OutputAvailableAsync())
{
T项;
if(来源TryReceive(外项))
{
等待任务。延迟(延迟);
等待target.SendAsync(项);
}
其他的
{
//这不应该发生
//其他任何人都不应该能够从源头接收信息
}
}
//TODO:如果源失败,则目标失败
target.Complete();
});
返回DataflowBlock.enclosure(源、目标);
}
我需要设计自定义datafloaw块,它的作用类似于缓冲区,但会在超时后使项目可用
那么,像这样的事情
public static TransformBlock<T, T> Delay<T>(Timespan delay)
{
return new TransformBlock<T, T>(async x =>
{
await Task.Delay(delay);
return x;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
});
}
公共静态传输块延迟(时间跨度延迟)
{
返回新的TransformBlock(异步x=>
{
等待任务。延迟(延迟);
返回x;
},
新的ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism=DataflowBlockOptions.Unbounded,
});
}
如果您仍然认为需要自定义块,请务必阅读,其中描述了您需要担心的所有锁。感谢您提供的指南链接,非常有用。
public static TransformBlock<T, T> Delay<T>(Timespan delay)
{
return new TransformBlock<T, T>(async x =>
{
await Task.Delay(delay);
return x;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
});
}