簡體   English   中英

Akka.net與ActorSelection的死鎖問題

[英]Akka.net deadlocking issue with ActorSelection

akka.net出現問題。 我需要訪問一個已經使用特定名稱創建的演員。 我可以從IActorContext檢索actor,但正在努力從ActorSystem訪問它。

我創建了一個名為GetOrCreateActor的方法,該方法嘗試使用ActorSelection獲取演員。 如果不存在,則捕獲將使用該名稱創建一個新演員。 如果確實存在,我希望它返回引用。 但是,它永遠不會從“ .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();
    };
}

與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方法-如果您沒有收到超時異常,則意味着您的應用程序在生成actor系統時陷入僵局(因為DI已配置)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM