4

假设我在 .NET 中使用数据流块。据说“这个数据流模型促进了基于参与者的编程”,这正是我想要在这里得到的。

但是,如果我处理来自 aBufferBlock<T>和消息处理器中的消息,我决定使用async/ await,这会将执行分叉到当前线程和等待任务的工作线程。

有什么方法可以防止参与者/消息处理器中的并发执行吗?

如果等待的任务使用带有本机回调的非阻塞 IO 操作执行,那很好。但我真的很想确保任何 .NET 代码只同步执行。

4

2 回答 2

3

这在很大程度上取决于您将如何处理这些消息。

如果你使用ActionBlockwith async action,不要设置它MaxDegreeOfParallelism(这意味着使用默认值 1 )并将其链接到BufferBlock,然后action将一次执行一条消息,不会有并行性。

如果您使用这样的循环手动处理消息:

while (await bufferBlock.OutputAvailableAsync())
{
    var message = await bufferBlock.ReceiveAsync();
    await ProcessMessageAsync(message);
}

然后消息也将一次处理一个。

但在这两种情况下,并不意味着一条消息将由单个线程处理。它可以由多个线程处理,但不能并行处理。这是因为在 之后await,执行可以在与暂停位置不同的线程上恢复。

如果您使用其他处理消息的方式(例如,使用上面的循环,但省略了awaitbefore ProcessMessageAsync()),则可以同时处理多条消息。

于 2014-01-03T20:34:20.730 回答
1

你误解了什么await。它不派生任何东西,它只是等待已经异步操作的结果。

用关键字标记的方法async不会自动变为异步的。只有在方法内部遇到异步操作时,才会异步async继续执行。关键字只是告诉编译器在异步操作完成应该在async哪里继续执行。

等待时不会浪费或损坏 ThreadPool 线程,因此您不应该试图限制、阻止或规避这一点。事实上,使用异步操作时,您可以获得更好的可伸缩性,因为 TPL 数据流使用的 ThreadPool 线程不会阻塞等待长时间运行的异步操作,如 I/O 或 Web 服务调用。

于 2013-12-30T13:39:04.440 回答