C# TPL数据流缓冲块<&燃气轮机;使用者在WPF的主线程中工作
我有一个简单的producer-consumer类,使用C# TPL数据流缓冲块<&燃气轮机;使用者在WPF的主线程中工作,c#,tpl-dataflow,C#,Tpl Dataflow,我有一个简单的producer-consumer类,使用BufferBlock对象发布改编自的消息,我的问题是在WPF应用程序中使用它会导致使用者在同一主线程中接收数据,而控制台应用程序在工作线程中执行数据。这是我的密码: public class DataflowProducerConsumer { BufferBlock<int> _buffer; public DataflowProducerConsumer() { _buffer =
BufferBlock
对象发布改编自的消息,我的问题是在WPF应用程序中使用它会导致使用者在同一主线程中接收数据,而控制台应用程序在工作线程中执行数据。这是我的密码:
public class DataflowProducerConsumer
{
BufferBlock<int> _buffer;
public DataflowProducerConsumer()
{
_buffer = new BufferBlock<int>();
var consumer = UseBufferBlock(_buffer);
}
public void Produce(int number)
{
_buffer.Post(number);
var actionBlock = UseActionBlock();
actionBlock.Post(number);
}
public async Task UseBufferBlock(ISourceBlock<int> source)
{
while (await source.OutputAvailableAsync())
{
int data = source.Receive();
// ...process data asyncron
Console.WriteLine("BufferBlock-Thread {0} received: {1}", Thread.CurrentThread.ManagedThreadId, data);
}
}
public ITargetBlock<int> UseActionBlock()
{
return new ActionBlock<int>(data =>
{
Console.WriteLine(string.Format("ActionBlock-Thread: {0} received: {1}", Thread.CurrentThread.ManagedThreadId, data));
});
}
}
嗯,我将
Post
改为SendAsync
,但没有成功。而ActionBlock
部分运行良好。有什么区别?我做错了什么?这与第三方物流数据流本身无关,而是与以下陈述有关:
await source.OutputAvailableAsync()
wait将捕获当前的同步上下文
,并对其进行后续处理(wait之后的方法的其余部分)。若并没有同步上下文(比如在控制台应用程序中),它会将延续发布到线程池线程
WPF有同步上下文,向其发布就是向UI线程发布(如Dispatcher.BeginInvoke()
),所以这就是您观察到的
要防止捕获当前同步上下文(因此-始终向线程池线程后置继续),请使用ConfigureAwait(false)
:
另外请注意,还有一个
ReceiveAsync()
方法,您可以使用它(并等待)代替同步Receive()
,尽管这与问题无关。解释得很好!谢谢我想我需要更多地了解同步上下文;-)@alex555这是一个很好的来源,来自这个特性的作者之一:为什么不直接链接这些块呢?
await source.OutputAvailableAsync()
while (await source.OutputAvailableAsync().ConfigureAwait(false))
{
int data = source.Receive();
// ...process data asyncron
Console.WriteLine("BufferBlock-Thread {0} received: {1}", Thread.CurrentThread.ManagedThreadId, data);
}