c# - 自定义 TaskScheduler、SynchronizationContext?

标签 c# multithreading concurrency task-parallel-library async-await

actors 中的异步等待支持

我正在将 actor 库 Akka 移植到 .NET ( https://github.com/rogeralsing/Pigeon ) 我想在我的 Actor 内部添加async/await支持。

这现在给我带来了一些问题,因为如果我使用默认调度程序,等待延续将在不考虑参与者并发边界的情况下运行。 这意味着,延续可能会在 actor 处理消息时运行,因为这会导致两个线程同时访问 actor 的内部状态。

如果我能以某种方式将任务安排到 Actor 自己的邮箱,并在邮箱运行中完成任务,这将解决问题。

 public class SomeActor : UntypedActor
 {
      protected override OnReceive(object message)
      {
           if (message is SomeMessage)
           {
              DoAsyncStuff();
           }
      }

      private async void DoAsyncStuff()
      {
          var res = await something..
          //this code will not respect the actor concurrency boundary
          //since it can run at the same time as OnReceive
          Console.WriteLine(res);
      }
 }

我确实有一个 actor 的线程静态上下文,所以当 actor 执行时,这个上下文被设置。 所以我可以很容易地从任务调度程序中查找活跃的参与者邮箱。 类似的东西:

public class ActorTaskScheduler : TaskScheduler
{
    protected override void QueueTask(Task task)
    {            
        var self = ActorCell.Current.Self;
        self.Tell(new ActorTask(task), ActorRef.NoSender);
    }

并且 ActorTask 消息可以由 actor 的系统消息处理程序处理。 到目前为止一切顺利。

我只是不知道下一步该做什么。 我可以直接覆盖当前的 TaskScheduler 吗? 该线程是静态的吗? 我只想在 actor 运行时应用此调度程序,它可能不会影响在 actor 外部运行的代码。

是否可以仅针对特定操作应用自定义任务调度程序?

最佳答案

Can I just over write the current TaskScheduler?

“设置”当前调度程序的正确方法是将委托(delegate)排队到您想要的调度程序。当委托(delegate)执行时,它将把该调度程序作为“当前”。

I do have a thread static context for the actor, so when the actor is executing, this context is set.

是否可以用其他方式做到这一点?因为这样您就有了更简单的解决方案。

我认为您可以在 ConcurrentExclusiveSchedulerPair.ExclusiveScheduler 中运行每个 actor。这意味着任何参与者代码都在线程池线程上运行;它可以是任何线程池线程,但ExclusiveScheduler 将确保一次只有一部分参与者代码运行。

这将 actor 抽象从线程“提升”到任务,如果可以的话,我会推荐这种方法。当你有异步 actor 时,它可以减轻内存和线程池的压力。当然,那时不能使用诸如线程静态之类的东西,因此您必须使用诸如逻辑调用上下文之类的东西或由自定义 SynchronizationContext 设置的 Current 值或任务调度器

关于c# - 自定义 TaskScheduler、SynchronizationContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21965772/

相关文章:

c# - 为什么 Chrome 会在我的 HTML 顶部添加一个正文,然后给我一个看似虚假的 err 消息?

c# - 使用简单注入(inject)器和 WebForms MVP 将运行时值传递给构造函数

c++ - 推断程序是否要使用线程

c# - 类之间的锁共享

java - 是否有可能使用两个锁且只有一个方法获取两个锁而所有其他方法仅获取一个锁而导致死锁?

c# - 事务性 CloudBlob

c# - 转换零日期时间与允许零日期时间

java - CyclicBarrier:导致屏障跳闸的 'x' 个线程中的 'y' 完成执行并终止

JavaFX 2 : background and Platform. runLater vs 任务/服务

c++ - 无锁容器如何对并发分区和排序使用react?