Akka.NET的Ask任务永远不会完成

7

我可能做了一些错误的事情,但它并不明显。我有以下代码:

 namespace test
    {
        class Program
            {
             static void Main(string[] args)

                {
                    using (var system = ActorSystem.Create("MySystem"))
                    {
                        var testPassRetriever = system.ActorOf<PrintActor>();
                        var task = testPassRetriever.Ask<PrintActorMsg>(new PrintActorMsg());

                        // prevent the application from exiting before message is handled
                        task.Wait();
                        Console.WriteLine("Finished.");
                        Console.ReadLine();
                    }
                }
        }
        class PrintActorMsg{}

        class PrintActor : ReceiveActor
        {
            public PrintActor()
            {
             Receive<PrintActorMsg>(msg => Console.WriteLine("foo"));
            }
        }
}// namespace test

问题在于由Ask返回的Task从未完成。其状态保持在等待激活状态。 "Foo"确实在命令行上打印出来,所以我知道该actor正在处理Print消息。我是否应该在重写的actor PrintMsg中执行其他操作以标记任务已完成?


在这里使用Task.Run会不会对你有好处呢? - whoisj
2
我不这么认为,我相信任务已经在 Akka.net 框架中运行。我已经得到了任务成功运行的结果。我只是一直等待任务完成。 - Matt Johnson
1
我认为这样做会绕过AKKA.net并且没有帮助,因为我正在尝试使用Akka.net来处理多线程。 - Matt Johnson
1
它不会返回。等待调用永远不会返回。 Task.Run(() => testPassRetriever.Ask<PrintActorMsg>(new PrintActorMsg())).Wait(); - Matt Johnson
1
让我们在聊天中继续这个讨论 - whoisj
显示剩余6条评论
2个回答

11
您使用了问询模式,但是从未发送回复消息。只有在从参与者接收到消息时,询问任务才会完成。(有时建议使用的)告知或火并忘模式不会这样做。

7
我必须将PrintActor更改为调用Sender.Tell(new PrintActorMsg())。 - Matt Johnson

0

仅供未来读者完整性考虑,由于OP的原始问题似乎不需要从被调用的Actor返回任何响应/结果负载,因此OP应该使用Tell模式而不是Ask模式,例如对于一些“fire and forget”分发场景:

 class PrintActor : ReceiveActor
 {
    public PrintActor()
    {
        // Response to the message, with no response
        Receive<PrintActorMsg>(msg => Console.WriteLine("foo"));
    }
 }

在调用程序中

var myActor = system.ActorOf<PrintActor>();
// One way 'fire and forget'
await myActor.Tell(new PrintActorMsg());

如果需要请求-响应类型的交互,则接收方演员需要通过明确的 Tell 返回消息给发送方(PrintResponse 是一个新的响应消息类):

 public class ResponseActor : ReceiveActor
 {
    public ResponseActor()
    {
       Receive<PrintActorMsg>(msg => {
         Console.WriteLine("foo"));

         // ... Other handling code here

         // Must return a response for an Ask
         Sender.Tell(new PrintResponse(), Self);
       });
    }
 }

并且这样调用

var response = await actor.Ask<PrintResponse>(new PrintActorMsg(), TimeSpan.FromSeconds(5));

请注意,添加异常处理也是一个好主意。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接