gpt4 book ai didi

c# - TPL 数据流 BufferBlock<> 消费者在 WPF 的主线程中工作

转载 作者:行者123 更新时间:2023-11-30 17:30:55 25 4
gpt4 key购买 nike

我有一个简单的生产者-消费者类,它使用 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));
});
}
}

在 main 或 Click-event 中执行的测试:

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

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

最佳答案

这与 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(),尽管这与问题无关有问题。

关于c# - TPL 数据流 BufferBlock<> 消费者在 WPF 的主线程中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48926580/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com