我有以下代码,它充当异步消费者:
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
我的设计问题:
答案 0 :(得分:1)
对于这个论坛,你的四个问题中有两个过于宽泛。只有你可以决定这是否是一个正确的方法&#34;为您的方案。同样,是否使用CancellationToken
的问题取决于您需要哪些功能。如果你需要能够取消操作,这可能是一个很好的方法,但不是唯一的方法,而且这里没有足够的细节知道什么是最好的。你也不能提供足够的细节,同时保持这个论坛的问题足够狭窄。
当然,如果您不需要取消操作,那么该问题的答案就是&#34;不,您不需要使用CancellationToken
&# 34; :)
至于其他两个问题,只有一个问题有明确答案:
不,你 。但强烈建议实际上长期运行的任务。这将有助于任务调度框架正确管理您的任务的线程。
你是否怀疑。由于您的ConsumeAsync()
方法为async void
,因此您显然无法等待它。执行此类操作的自然方法是编写更像这样的代码:
private Task ConsumeAsync()
{
return Task.Run(() => this.Listen());
}
async Task SomeMethodSomewhereElse()
{
try
{
await ConsumeAsync();
}
catch (...)
{
// An exception thrown from your long-running task will be caught here
}
}
请注意,ConsumeAsync()
方法本身并不需要async
。您只需返回已创建的Task
,并且将完全相同(更好,更有效......但主要的是不添加完全不必要的额外代码)。
你编写它的方式,你将不得不去做很多额外的工作来捕捉抛出的异常(即直接从SynchronizationContext
处理它)。也许你这样做了,也许你没有。你没有显示该代码,所以我假设你没有。