【发布时间】:2015-01-09 05:00:32
【问题描述】:
我有以下代码,它充当异步消费者:
private readonly Object sync;
private async void ConsumeAsync()
{
// The reason why I have an await here is to yield the control to the caller, e.g: if an exception happens inside the Listen method, it's being propagated and can be handled in caller codes.
await Task.Run(() => this.Listen());
}
private void Listen()
{
...
while (true)
{
lock (sync)
{
while (<blocking-condition>)
{
Monitor.Wait(sync);
}
}
// Consuming happens here
}
}
// Changing the blocking condition happens outside the infinite loop with proper Monitor.Pulse usage
我的设计关注点:
- 我有一个异步 void 即发即弃的方法,如果没有消耗,则必须阻止该方法。这是一个正确的方法吗?
- 我必须对任务使用 LongRunning 选项吗?
- 我必须使用 CancellationToken 吗?
- 我是否将异常正确地传播到更高级别的异常处理程序?
【问题讨论】:
-
最佳实践是avoid
async voidmethods - 作为“当异步任务或异步任务方法抛出异常时,该异常被捕获并放置在任务对象上。使用异步无效方法,没有 Task 对象,因此从异步 void 方法抛出的任何异常都将直接在异步 void 方法启动时处于活动状态的 SynchronizationContext 上引发。" ... -
但是如果我使用 BlockingCollection 或其他 3rd 方集合(如 RabbitMQ 共享队列),它可以在 while (true) 循环中使用 Monitor.Wait 阻塞其调用线程?
标签: c# multithreading task-parallel-library async-await