【问题标题】:TPL Dataflow BufferBlock<> consumer works in main-thread in WPFTPL Dataflow BufferBlock<> 消费者在 WPF 的主线程中工作
【发布时间】:2018-02-22 11:43:53
【问题描述】:

我有一个简单的生产者-消费者类,它使用 BufferBlock 对象发布改编自 TPL Dataflow Docs 的消息,我的问题是在 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));
        });
    }
}

在主事件或点击事件中执行的测试:

var obj = new DataflowProducerConsumer();
obj.Produce(19);

好吧,我将Post 更改为SendAsync 没有成功。 ActionBlock 部分运行良好。有什么不同?我做错了什么?

【问题讨论】:

  • 你为什么不直接链接块?

标签: c# tpl-dataflow


【解决方案1】:

这与 TPL DataFlow 本身无关,而是与以下语句有关:

await source.OutputAvailableAsync()

await 将捕获当前的SynchronizationContext 并将继续(等待之后的方法的其余部分)发送到它。如果没有同步上下文(例如在控制台应用程序中) - 它会将延续发布到线程池线程。

WPF 具有同步上下文,向它发布内容就是发布到 UI 线程(如 Dispatcher.BeginInvoke()),所以这就是您所观察到的。

为防止捕获当前同步上下文(因此 - 始终将延续发布到线程池线程),请使用 ConfigureAwait(false)

while (await source.OutputAvailableAsync().ConfigureAwait(false))
{
    int data = source.Receive();

    // ...process data asyncron
    Console.WriteLine("BufferBlock-Thread {0} received: {1}", Thread.CurrentThread.ManagedThreadId, data);
}

另请注意,有 ReceiveAsync() 方法,您可以使用(和等待)而不是同步 Receive(),尽管这与所讨论的问题无关。

【讨论】:

猜你喜欢
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多