使用async / await进行资源锁定

时间:2012-10-02 16:43:41

标签: c# .net synchronization locking async-await

我有一个应用程序,我有一个可以被多个客户端访问的共享资源(一个Motion系统)。我有个别操作需要在移动期间访问系统,如果同时请求冲突操作,则应该抛出“忙”异常。我也有序列发生器需要获得对Motion系统的独占访问权,以执行多个操作,并穿插其他操作;在整个序列中,没有其他客户端能够运行操作。

我传统上使用Thread-affinity接近它,因此Thread可以请求独占访问并运行与操作相对应的阻塞调用。虽然线程具有访问权限,但没有其他线程可以使用该资源。我现在遇到的问题是我已经开始使用async / await模式实现我的系统,以允许更清晰的序列器实现。问题是现在我的音序器并不总是在同一个线程上运行;活动线程可以在回调过程中发生变化,因此不再容易确定我是否处于有效的上下文中以保持运行操作。需要注意的一点是,某些操作本身由等待组成,这意味着序列和单个操作都可以跨越多个线程。

我的问题:是否有人知道在异步/等待导致线程切换时获取独占访问权的好模式?

作为参考,我考虑了一些事情:

  1. 我可以创建一个自定义的SynchronizationContext,它将序列持续时间内的所有sequencer调用封送回单个Thread。这样可以让我重用现有的线程相关访问管理代码。缺点是,无论何时执行序列或操作,都需要专用线程(因为操作也可以跨越多个线程。)

  2. 创建一个可获取的访问令牌以传递给Operation方法,以证明您已获得访问权限。这有使用令牌参数膨胀方法的缺点。

  3. 使用(2)中的访问令牌方法,但为Operations接口创建一个重复的接口实现,以便可以使用令牌“烘焙”实例化包装器。这会创建一些丑陋的胶水代码,但它会清除序列代码,以便它不再需要将令牌传递给每个方法。

2 个答案:

答案 0 :(得分:22)

  

我的问题:是否有人知道在异步/等待导致线程切换时获取独占访问权的好模式?

是的,您可以使用AsyncLock,这也是AsyncEx library的一部分。如果你想进行“TryLock”操作,那么你可能需要创建自己的原语。

您确实失去了进行安全检查的一些功能:无法检查当前正在执行的线程是否具有特定的AsyncLock

其他选项包括ConcurrentExclusiveSchedulerPair(我在博客中提到here)或TPL数据流。

答案 1 :(得分:11)

这里有SemaphoreSlim.WaitAsync。 (我在a similar question中找到了它。)