与ActorSelection的Akka.net死锁问题

时间:2016-05-31 15:13:42

标签: c# akka akka.net

akka.net有问题。我需要访问一个我已经使用特定名称创建的actor。我可以从IActorContext中检索actor,但我很难从ActorSystem访问它。

我创建了一个名为GetOrCreateActor的方法,它尝试使用ActorSelection获取actor。如果它不存在,catch将创建一个名为的新actor。如果确实存在,我希望它返回引用。但是,它永远不会从'.Result'返回。假设这可能是某种死锁问题。

public static IActorRef GetOrCreateActor<T>(this ActorSystem actorSystem, string actorPath, string name = null) where T : ActorBase
    {
        try
        {
            return actorSystem.ActorSelection(actorPath).ResolveOne(TimeSpan.FromSeconds(1)).Result;
        }
        catch 
        { 

            return actorSystem.ActorOf(actorSystem.DI().Props<T>(), name); 
        }
    }

修改 我试图在下面包含一个简化版本的调用代码。

使用AutoFac在IOC容器中创建actor系统(ExampleActor是我尝试访问的ReceiveActor):

containerBuilder.RegisterAssemblyTypes(typeof(ExampleActor).Assembly).Where(x => x.Name.EndsWith("Actor")); 
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
    var system = ActorSystem.Create("ExampleActorSystem");
    new AutoFacDependencyResolver(lazyContainer.Value, system);
    return system;
}).As<ActorSystem>().SingleInstance();
return lazyContainer.Value;

然后将ActorSystem注入另一个类,我在其中调用GetOrCreateActor方法(通过Execute方法):

public class ExampleCommand : IExampleCommand
{
    private readonly ActorSystem _actorSystem;
    public ExampleCommand(ActorSystem actorSystem)
    {
        _actorSystem = actorSystem;
    }
    public void Execute()
    {
        SendMessage();
    }
    private void SendMessage()
    {
        string message = new Message();
        _actorSystem.GetOrCreateActor<ExampleActor>("akka://ExampleActorSystem/user/ExampleActor", "ExampleActor").Tell(message);
    }
}

将从RESTful端点

调用上述命令
public ExampleGetModule(IExampleCommand exampleCommand)
{
    Get["/api/createExample"] = parameters =>
    {
        exampleCommand.Execute();
    };
}

1 个答案:

答案 0 :(得分:0)

你的死锁问题看起来更像是你如何使用你的容器而不是Akka.NET:

var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
    var system = ActorSystem.Create("ExampleActorSystem");
    new AutoFacDependencyResolver(lazyContainer.Value, system);
    return system;
}).As<ActorSystem>().SingleInstance();

就这里可能出现的问题而言,自我引用的Lazy<T>类型是一种臭名昭着的竞争条件来源。如果lazyContainer.Value的输出取决于containerBuilder.Build的输入,则不应在此注册方法中调用containerBuilder.Register

最后一件事是使用逐步调试来确保您的应用程序实际调用此处的ResolveOne方法 - 如果您没有收到超时异常,那么这意味着您的应用程序正在死锁制作演员系统(因为如何配置DI)。