自定义TaskScheduler,SynchronizationContext?

Rog*_*son 3 c# concurrency multithreading task-parallel-library async-await

async等待演员内部的支持

我将演员lib Akka移植到.NET(https://github.com/rogeralsing/Pigeon)我想我的演员中添加async/await支持.

这给了我一些问题,因为如果我使用默认调度程序,await continuation将运行与actor并发boundarys相关.这意味着,当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);
      }
 }
Run Code Online (Sandbox Code Playgroud)

我确实有一个actor的线程静态上下文,所以当actor执行时,这个上下文被设置.所以我可以轻松地从任务调度程序中查找活动的actor邮箱.有点像:

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

并且ActorTask消息可以由actor的系统消息处理程序处理.到现在为止还挺好.

我只是不知道接下来该做什么.我可以过度编写当前的TaskScheduler吗?该线程是静态的吗?我只是想在actor运行时应用这个调度程序,它可能不会影响在actor之外运行的代码.

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

Ste*_*ary 7

我可以过度编写当前的TaskScheduler吗?

"设置"当前调度程序的正确方法是将委托排队到所需的调度程序.当委托执行时,它将该调度程序作为"当前".

我确实有一个actor的线程静态上下文,所以当actor执行时,这个上下文被设置.

是否有可能以另一种方式做到这一点?因为那时你有一个更简单的解决方案.

我想你可以在里面运行每个演员ConcurrentExclusiveSchedulerPair.ExclusiveScheduler.这意味着任何actor代码都在线程池线程上运行; 它可以是任何线程池线程,但是ExclusiveScheduler将确保一次只运行一部分actor代码.

这会将演员抽象从线程"提升"到任务,这是我建议的方法,如果你能做到的话.当你有异步演员时,它减轻了内存和线程池的压力.当然,当时不能使用线程静态之类的东西,所以你必须使用类似逻辑调用上下文或Current由自定义SynchronizationContext或设置的值TaskScheduler.