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之外运行的代码.
这是否可以仅针对特定操作应用自定义任务调度程序?
我可以过度编写当前的TaskScheduler吗?
"设置"当前调度程序的正确方法是将委托排队到所需的调度程序.当委托执行时,它将该调度程序作为"当前".
我确实有一个actor的线程静态上下文,所以当actor执行时,这个上下文被设置.
是否有可能以另一种方式做到这一点?因为那时你有一个更简单的解决方案.
我想你可以在里面运行每个演员ConcurrentExclusiveSchedulerPair.ExclusiveScheduler
.这意味着任何actor代码都在线程池线程上运行; 它可以是任何线程池线程,但是ExclusiveScheduler
将确保一次只运行一部分actor代码.
这会将演员抽象从线程"提升"到任务,这是我建议的方法,如果你能做到的话.当你有异步演员时,它减轻了内存和线程池的压力.当然,当时不能使用线程静态之类的东西,所以你必须使用类似逻辑调用上下文或Current
由自定义SynchronizationContext
或设置的值TaskScheduler
.