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/