Can a Task have multiple awaiters?
我正在为 Windows 8 项目使用异步服务,并且该服务有一些异步调用,一次只能调用一次。
1
2 3 4 5 6 7 8 |
public async Task CallThisOnlyOnce() { PropagateSomeEvents(); await SomeOtherMethod(); PropagateDifferentEvents(); |
由于不能将异步调用封装在 lock 语句中,我想到了使用
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
private Task _callThisOnlyOnce; public Task CallThisOnlyOnce() { if(_callThisOnlyOnce != null && _callThisOnlyOnce.IsCompleted) _callThisOnlyOnce = null; if(_callThisOnlyOnce == null) return _callThisOnlyOnce; private async Task CallThisOnlyOnceAsync() await SomeOtherMethod(); PropagateDifferentEvents(); |
因此,您最终会得到调用
这是一种”有效”的方法吗?还是这种方法有一些缺点?
一个任务可以有多个等待者。但是,正如 Damien 指出的那样,您提出的代码存在严重的竞争条件。
如果您希望每次调用方法时都执行代码(但不是同时),请使用
您提出的解决方案尝试组合多个调用,如果代码尚未运行,则再次执行该代码。这更棘手,解决方案在很大程度上取决于您需要的确切语义。这是一个选项:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
private AsyncLock mutex = new AsyncLock(); private Task executing; public async Task CallThisOnlyOnceAsync() await action; private async Task DoCallThisOnlyOnceAsync() await SomeOtherMethod(); PropagateDifferentEvents(); using (await mutex.LockAsync()) |
使用
附言我的 AsyncEx 库中有
如果可能涉及多个线程,此代码看起来非常”活泼”。
一个例子(我相信还有更多)。假设
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Thread 1 Thread 2
public Task CallThisOnlyOnce() if(_callThisOnlyOnce == null) if(_callThisOnlyOnce == null) return _callThisOnlyOnce; return _callThisOnlyOnce; |
您现在有 2 个呼叫同时运行。
对于多个等待者,是的,您可以这样做。我确定我在某处看到过 MS 的示例代码,其中显示了优化,例如
但是,我未能找到此代码示例。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/269654.html