自定义TaskScheduler,SynchronizationContext?

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); } } 

我确实有一个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); } 

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

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

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

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

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

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

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

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

这会将演员抽象从线程“提升”到任务,这是我建议的方法,如果你能做到的话。 当你有异步演员时,它减轻了内存和线程池的压力。 当然,当时不能使用线程静态等内容,因此必须使用逻辑调用上下文或由自定义SynchronizationContextTaskScheduler设置的Current值。