一个任务可以有多个awaiters? [英] Can a Task have multiple awaiters?

查看:192
本文介绍了一个任务可以有多个awaiters?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我玩弄周围异步服务为Windows 8项目,有此服务,这只能在一个时间一度被称为一些异步调用。

I am toying around with an async service for a Windows 8 project and there are some async calls of this service, which should only be called once at a time.

 public async Task CallThisOnlyOnce()
 {
      PropagateSomeEvents();

      await SomeOtherMethod();

      PropagateDifferentEvents();
 }



既然你不能封装在一个锁声明一个异步调用,我想用的在 AsyncLock 模式,但不是我想我不妨试试这样的:

Since you cannot encapsulate an async call in a lock statement, i thought of using the AsyncLock pattern, but than i thought i might as well try something like this:

 private Task _callThisOnlyOnce;
 public Task CallThisOnlyOnce()
 {
      if(_callThisOnlyOnce != null && _callThisOnlyOnce.IsCompleted)
         _callThisOnlyOnce = null;

      if(_callThisOnlyOnce == null)
         _callThisOnlyOnce = CallThisOnlyOnceAsync();

      return _callThisOnlyOnce;
 }

 private async Task CallThisOnlyOnceAsync()
 {
      PropagateSomeEvents();

      await SomeOtherMethod();

      PropagateDifferentEvents();
 }



所以你最终会与呼叫 CallThisOnlyOnceAsync 只执行一次simultanously和多个awaiters迷上了相同的任务。

Therefore you would end up with the call CallThisOnlyOnceAsync only executed once simultanously, and multiple awaiters hooked on the same Task.

这是这样做的一个有效的方式还是有一些缺点这种方法?

Is this a "valid" way of doing this or are there some drawbacks to this approach?

推荐答案

一个任务可以有多个awaiters。然而,正如达指出,有一个与你的建议代码严重的竞争条件。

A task can have multiple awaiters. However, as Damien pointed out, there's serious race conditions with your proposed code.

如果您希望您的每一个方法被调用(但不能同时使用)时执行的代码,然后使用 AsyncLock 。如果你想一次执行的代码,然后用 AsyncLazy

If you want the code executed each time your method is called (but not simultaneously), then use AsyncLock. If you want the code executed only once, then use AsyncLazy.

您建议的解决方案试图将多个呼叫相结合,再次执行代码,如果它尚未运行。这是更靠谱,而且该解决方案在很大程度上取决于你所需要的确切的语义。这里有一个选项:

Your proposed solution attempts to combine multiple calls, executing the code again if it is not already running. This is more tricky, and the solution heavily depends on the exact semantics you need. Here's one option:

private AsyncLock mutex = new AsyncLock();
private Task executing;

public async Task CallThisOnlyOnceAsync()
{
  Task action = null;
  using (await mutex.LockAsync())
  {
    if (executing == null)
      executing = DoCallThisOnlyOnceAsync();
    action = executing;
  }

  await action;
}

private async Task DoCallThisOnlyOnceAsync()
{
  PropagateSomeEvents();

  await SomeOtherMethod();

  PropagateDifferentEvents();

  using (await mutex.LockAsync())
  {
    executing = null;
  }
}



它也可以做到这一点与互锁,但代码获取难看。

PS我有 AsyncLock AsyncLazy 和其他异步 -ready原语我 AsyncEx库

P.S. I have AsyncLock, AsyncLazy, and other async-ready primitives in my AsyncEx library.

这篇关于一个任务可以有多个awaiters?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆