使用async/await进行资源锁定

32

我有一个应用程序,其中有一个共享资源(Motion系统),可以被多个客户端访问。我有独立的操作需要在移动期间访问系统,并且如果请求冲突操作,则应抛出“繁忙”异常。我还有需要获取Motion系统的独占访问权限以执行多个操作的序列控制器,这些操作与其他操作交替进行; 在整个序列期间,没有其他客户端能够运行操作。

我传统上使用线程关联来解决这个问题,以便线程可以请求独占访问并运行对应操作的阻塞调用。当线程具有访问权限时,没有其他线程可以使用该资源。我现在遇到的问题是,我已经开始使用async/await模式实现我的系统,以允许更清晰的序列控制器实现。问题是现在我的序列控制器不总是在同一个线程上运行; 在回调过程中,活动线程可能会更改,因此不再容易确定是否处于有效上下文中以继续运行操作。需要注意的一点是,某些操作本身由awaits组成,这意味着序列和单个操作都可以跨越多个线程。

我的问题:有没有人知道在异步/等待时处理获取独占访问权限的好方法?

供参考,我已经考虑了一些事情:

  1. 我可以创建一个自定义同步上下文,为序列期间的所有序列调用调度回单个线程。这样做的好处是允许我重用现有的线程关联访问管理代码。缺点是每当我执行序列或操作(因为操作也可以跨越多个线程)时都需要分配一个线程。

  2. 创建可获取的访问令牌以传递给操作方法以证明您已获得访问权限。这种方法的缺点是会使方法膨胀并增加令牌参数。

  • 使用第2种访问令牌方法,但为Operations接口创建一个重复的接口实现,以便可以实例化一个包装器来嵌入访问令牌。这会产生一些丑陋的粘合代码,但它可以清理掉Sequencer代码,使其不再需要将令牌传递给每个方法。

  • 2个回答

    24
    我的问题:是否有人知道如何处理在异步/等待时存在线程切换的情况下获取独占访问的良好模式?
    是的,您可以使用AsyncLock,它也作为我的AsyncEx库的一部分提供。如果您想要进行“TryLock”类型的操作,那么您可能需要创建自己的原语。
    您确实会失去一些进行安全检查的能力:无法检查当前执行的线程是否具有特定的AsyncLock
    其他选项包括ConcurrentExclusiveSchedulerPair(我在这里中发表了博客)或TPL数据流。

    我会将这标记为有用阅读的答案。最终,我创建了包含访问检查的接口代理。然后,我可以分发一个特殊的一次性“独占访问”代理,防止其他代理实例在其存在期间使用系统。 - Dan Bryant

    12

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接