gpt4 book ai didi

c# - 使用 async/await 时使用自定义 SynchronizationContext 序列化执行

转载 作者:太空狗 更新时间:2023-10-29 20:24:08 24 4
gpt4 key购买 nike

我的团队正在使用 C# 5.0 中的 async/await 开发多线程应用程序。在实现线程同步的过程中,经过多次迭代,我们想出了一个(可能是新颖的?)带有内部锁的新 SynchronizationContext 实现:

  1. 调用 Post 时:
    • 如果可以获取锁,则立即执行委托(delegate)
    • 如果无法获取锁,则委托(delegate)排队
  2. 调用 Send 时:
    • 如果可以获取锁,则执行委托(delegate)
    • 如果不能获取锁,则线程被阻塞

在所有情况下,在执行委托(delegate)之前,上下文将自身设置为当前上下文,并在委托(delegate)返回时恢复原始上下文。

这是一种不寻常的模式,因为我们显然不是第一个编写此类应用程序的人,所以我想知道:

  1. 这个模式真的安全吗?
  2. 是否有更好的方法来实现线程同步?

这是 SerializingSynchronizationContext 的源代码和 GitHub 上的演示.

使用方法如下:

  • 每个需要保护的类都创建自己的上下文实例,如互斥量。
  • 上下文是可等待的,所以像下面这样的语句是可能的。

    await myContext;

    这只会导致方法的其余部分在上下文的保护下运行。

  • 该类的所有方法和属性都使用此模式来保护数据。在等待之间,一次只有一个线程可以在上下文上运行,因此状态将保持一致。当到达 await 时,允许下一个计划线程在上下文中运行。
  • 自定义 SynchronizationContext 可以与 AsyncLock 结合使用,如果需要保持原子性,即使是等待表达式也是如此。
  • 类的同步方法也可以使用自定义上下文进行保护。

最佳答案

拥有一个从不同时运行多个操作的同步上下文当然不是新奇的,也一点也不坏。 Here你可以看到 Stephen Toub 在两年前描述了如何制作一个。 (在这种情况下,它只是用作创建消息泵的工具,这实际上听起来可能正是您想要的,但即使不是,您也可以从解决方案中提取同步上下文并单独使用它。)

拥有单线程同步上下文当然在概念上很有意义。所有表示 UI 状态的同步上下文都是这样的。 winforms、WPF、winphone 等同步上下文都确保一次只运行来自该上下文的单个操作。

令人担忧的是:

In all cases, before executing the delegate, the context sets itself as the current context and restores the original context when the delegate returns.

我会说上下文本身不应该这样做。如果调用者希望此同步上下文成为当前上下文,他们 可以设置它。如果他们想将它用于当前上下文之外的其他内容,您应该允许他们这样做。有时您想使用同步上下文而不将其设置为当前上下文来同步对特定资源的访问;在这种情况下,只有专门访问该资源的操作才需要使用此上下文。

关于c# - 使用 async/await 时使用自定义 SynchronizationContext 序列化执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20999732/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com