2016-05-31 86 views
2

遇到akka.net問題。我需要訪問我已經用特定名稱創建的演員。我可以從IActorContext中檢索actor,但是我很難從ActorSystem中訪問它。Akka.net與ActorSelection的死鎖問題

我已經創建了一個名爲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); 
     } 
    } 

編輯 我一直在努力,包括下面的調用代碼的簡化版本。

演員系統是在IOC容器使用AutoFac創建(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(); 
    }; 
} 
+0

你能提供更多的信息嗎?例如:死鎖發生時如何調用該方法?它是調用'GetOrCreateActor'的'async'方法嗎? – easuter

+0

我已編輯該問題以提供更多信息。 – Kelly

回答

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>類型一個臭名昭着的種族條件的來源。如果containerBuilder.Build的輸出取決於containerBuilder.Register的輸入,則不應在此註冊方法中調用lazyContainer.Value

最後一件事是使用逐步調試來確保您的應用程序實際調用了ResolveOne方法 - 如果您沒有收到超時異常,那麼這意味着您的應用程序在生成actor系統時發生死鎖(由於DI的配置方式)。