如何使用async / await模式同步共享资源

时间:2015-02-17 19:24:41

标签: .net multithreading asynchronous async-await asp.net-4.5

我正在开发一些基本上是pub / sub框架的软件。

在订阅时,我必须记录正在订阅的内容,并且我需要同时进行订阅和取消订阅原子操作。连接由guid标识,并且可以具有多个订阅(例如,Alice想要NEWS和WEATHER)。因此,一旦Alice与ID建立连接,她可以Subscribe()多次处理她关心的事件。

简单来说,我的订阅看起来像这样:

ConcurrentDictionary<string, List<string>> _subscriptionsForConnection;
async Task Subscribe()
{
   List<string> subscriptikons = _subscriptionsForConnection.GetOrAdd(connectionId, MakeNewList);
   await underlyingComponentA.SubscribeAsync(xxx);
   subscriptions.Add(xxx);
   await underlyingComponentB.SubscribeAsync(xxx);
}

问题是,我需要同步字典以确保订阅和取消订阅操作不会以订阅列表最终未准确表示订阅状态的方式重叠。

从概念上讲,我想要的是:

lock(_subscriptionsForconnection)
{
    subscriptions = GetOrAdd();
    await SubscribeA();
    subscriptions.Add();
    await SubscribeB();
}

然而.net 4.5不允许您awaitlock由于多种原因,包括您的执行可能会在另一个上下文中恢复,从而无法解锁。 (这意味着Monitor.Enter / Exit不起作用)。

另一种方法是序列化两个底层组件调用并使用Wait()方法使它们同步运行,但这似乎是错误的。

我觉得我可能认为这个问题不对,所以我欢迎您的建议。

其他详细信息 我从我的解释中抽象出一些细节,以使其更清晰。对于那些想知道的人。 - 我正在开发SignalR之上的组件。 underlyingComponentB.SubscribeAsync实际上是Groups.Add调用。 - underlyingComponentA.SubscribeAsync是一个外部消息总线,它将驱动我的组件

1 个答案:

答案 0 :(得分:1)

使用SemaphoreSlim.WaitAsync代替lock