Dependency injection Akka.DI.Autofac没有创建actor
我正在尝试设置DI,后面是正式的akka.net文档()。然而,演员从不创造。下面我的代码有什么问题Dependency injection Akka.DI.Autofac没有创建actor,dependency-injection,autofac,akka.net,Dependency Injection,Autofac,Akka.net,我正在尝试设置DI,后面是正式的akka.net文档()。然而,演员从不创造。下面我的代码有什么问题 public class Worker: ReceiveActor { public Worker() { Receive<string>(m => Console.WriteLine("Worker is working")); } } public class WorkerManager : ReceiveActor { p
public class Worker: ReceiveActor
{
public Worker()
{
Receive<string>(m => Console.WriteLine("Worker is working"));
}
}
public class WorkerManager : ReceiveActor
{
public WorkerManager()
{
Receive<string>(m => Console.WriteLine("Manager start supervise"));
}
protected override void PreStart()
{
Context.ActorOf(Context.DI().Props<Worker>(), "Worker1");
}
}
class Program
{
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Worker>();
builder.RegisterType<WorkerManager>();
var system = ActorSystem.Create("DiTestSystem");
IContainer container = builder.Build();
IDependencyResolver resolver = new AutoFacDependencyResolver(container, system);
var manageRef = system.ActorOf(system.DI().Props<WorkerManager>(), "Manager1");
manageRef.Tell("Hello");
system.ActorSelection("/user/Manager1/Worker1").Tell("Hello");
Console.ReadLine();
}
}
公共类工作人员:ReceiveActor
{
公职人员()
{
接收(m=>Console.WriteLine(“工人正在工作”);
}
}
公共类WorkerManager:ReceiveActor
{
公共WorkerManager()
{
接收(m=>Console.WriteLine(“管理器启动管理”);
}
受保护的覆盖无效预启动()
{
Context.ActorOf(Context.DI().Props(),“Worker1”);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
ContainerBuilder=新的ContainerBuilder();
RegisterType();
RegisterType();
var system=ActorSystem.Create(“数据测试系统”);
IContainer容器=builder.Build();
IDependencyResolver解析器=新的AutoFacDependencyResolver(容器、系统);
var manageRef=system.ActorOf(system.DI().Props(),“Manager1”);
manageRef.Tell(“你好”);
system.ActorSelection(“/user/Manager1/Worker1”).Tell(“Hello”);
Console.ReadLine();
}
}
当运行代码时,我得到了这个
[信息][24/04/2017 1:50:11 AM][线程0006][akka://DiTestSystem/user/Manager1/Worker1]来自的消息字符串akka://DiTestSystem/deadLetters 到akka://DiTestSystem/user/Manager1/Worker1 没有交货。遇到1封死信。
Manager start supervise我发现使用Autofac无法足够快地创建Actor 当我添加Thread.Sleep(20)时,最后,正确地创建了actor
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<WorkerManager>();
builder.RegisterType<Worker>();
var system = ActorSystem.Create("DiTestSystem");
IContainer container = builder.Build();
IDependencyResolver resolver = new AutoFacDependencyResolver(container, system);
var manageRef = system.ActorOf(system.DI().Props<WorkerManager>(), "Manager1");
Thread.Sleep(20); // ADDED THIS LINE
manageRef.Tell("Hello");
system.ActorSelection("/user/Manager1/Worker1").Tell("Hello");
Console.ReadLine();
}
static void Main(字符串[]args)
{
ContainerBuilder=新的ContainerBuilder();
RegisterType();
RegisterType();
var system=ActorSystem.Create(“数据测试系统”);
IContainer容器=builder.Build();
IDependencyResolver解析器=新的AutoFacDependencyResolver(容器、系统);
var manageRef=system.ActorOf(system.DI().Props(),“Manager1”);
Thread.Sleep(20);//添加了这一行
manageRef.Tell(“你好”);
system.ActorSelection(“/user/Manager1/Worker1”).Tell(“Hello”);
Console.ReadLine();
}
我认为这是一个相当大的问题,因为这种方法不能保证参与者总是在睡眠时间创建/解决问题
我一直对这个问题持开放态度,因为我认为这不是一个正确的答案。我发现,使用Autofac无法足够快地创建Actor 当我添加Thread.Sleep(20)时,最后,正确地创建了actor
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<WorkerManager>();
builder.RegisterType<Worker>();
var system = ActorSystem.Create("DiTestSystem");
IContainer container = builder.Build();
IDependencyResolver resolver = new AutoFacDependencyResolver(container, system);
var manageRef = system.ActorOf(system.DI().Props<WorkerManager>(), "Manager1");
Thread.Sleep(20); // ADDED THIS LINE
manageRef.Tell("Hello");
system.ActorSelection("/user/Manager1/Worker1").Tell("Hello");
Console.ReadLine();
}
static void Main(字符串[]args)
{
ContainerBuilder=新的ContainerBuilder();
RegisterType();
RegisterType();
var system=ActorSystem.Create(“数据测试系统”);
IContainer容器=builder.Build();
IDependencyResolver解析器=新的AutoFacDependencyResolver(容器、系统);
var manageRef=system.ActorOf(system.DI().Props(),“Manager1”);
Thread.Sleep(20);//添加了这一行
manageRef.Tell(“你好”);
system.ActorSelection(“/user/Manager1/Worker1”).Tell(“Hello”);
Console.ReadLine();
}
我认为这是一个相当大的问题,因为这种方法不能保证参与者总是在睡眠时间创建/解决问题
我对这个问题持开放态度,因为我认为这不是一个正确的答案。这里的问题是一个竞赛条件。无论是否使用DI容器创建参与者,都可能发生这种情况 当使用actor系统时,您需要记住所有事情都是异步发生的。您可以在将消息发送到
WorkerManager
参与者后继续编写代码,但这并不意味着消息实际上已被接收和处理。它实际上被发布到一个邮箱,以便参与者在准备就绪时在另一个线程上处理
如果您有一个WorkerManager
actor,最好不要尝试直接访问Worker
actor。就像在现实生活中一样,你通常会要求经理组织一些要做的工作,然后经理会依次决定需要哪些员工,并将必要的工作分配给他们
Akka.NET有一个适用于此类场景的工具。我已经用一些额外的日志记录和路由器配置更新了您的示例代码
void Main()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Worker>();
builder.RegisterType<WorkerManager>();
var container = builder.Build();
var system = ActorSystem.Create("DITestSystem");
var resolver = new AutoFacDependencyResolver(container, system);
var manager = system.ActorOf(system.DI().Props<WorkerManager>(), "Manager");
Console.WriteLine("Program: Created Manager");
for (int i = 0; i < 10; i++)
{
manager.Tell("Hello");
}
Console.ReadKey(true);
}
public class Worker : ReceiveActor
{
public Worker()
{
Receive<string>(m => Console.WriteLine($"Worker {Context.Self.Path.Name} received: {m}"));
}
protected override void PreStart()
{
Console.WriteLine($"PreStart: {Context.Self.Path}");
}
}
public class WorkerManager : ReceiveActor
{
IActorRef worker;
public WorkerManager()
{
Receive<string>(m =>
{
Console.WriteLine($"Manager received: {m}");
worker.Tell(m);
});
}
protected override void PreStart()
{
Console.WriteLine($"PreStart: {Context.Self.Path}");
var props = Context.DI().Props<Worker>().WithRouter(new RoundRobinPool(5));
worker = Context.ActorOf(props, "Worker");
}
}
这将导致ManagerActor
以循环方式将消息转发给5个子Worker
参与者。消息路由由您负责,因此无需直接与工作者
参与者交互
var props = Context.DI().Props<Worker>().WithRouter(new RoundRobinPool(5));
现在,该示例在获得对它的引用后,还会立即向ManagerActor
发送10条消息
for (int i = 0; i < 10; i++)
{
manageRef.Tell("Hello");
}
这是另一个的输出
Program: Created Manager
PreStart: akka://DITestSystem/user/Manager
PreStart: akka://DITestSystem/user/Manager/Worker/$b
PreStart: akka://DITestSystem/user/Manager/Worker/$c
PreStart: akka://DITestSystem/user/Manager/Worker/$d
PreStart: akka://DITestSystem/user/Manager/Worker/$f
PreStart: akka://DITestSystem/user/Manager/Worker/$e
Manager received: Hello
Manager received: Hello
Manager received: Hello
Manager received: Hello
Worker $d received: Hello
Worker $e received: Hello
Manager received: Hello
Manager received: Hello
Manager received: Hello
Manager received: Hello
Manager received: Hello
Worker $f received: Hello
Worker $e received: Hello
Manager received: Hello
Worker $f received: Hello
Worker $b received: Hello
Worker $b received: Hello
Worker $c received: Hello
Worker $c received: Hello
Worker $d received: Hello
您可以看到,在第一次运行中,WorkerManager
在创建任何子Worker
参与者之前已收到所有消息。在第二次运行中,它在接收任何消息之前创建了所有子工作者参与者
要记住的要点是,最好与消息沟通,不要对事情发生的时间做出假设。这里的问题是竞争条件。无论是否使用DI容器创建参与者,都可能发生这种情况
当使用actor系统时,您需要记住所有事情都是异步发生的。您可以在将消息发送到WorkerManager
参与者后继续编写代码,但这并不意味着消息实际上已被接收和处理。它实际上被发布到一个邮箱,以便参与者在准备就绪时在另一个线程上处理
如果您有一个WorkerManager
actor,最好不要尝试直接访问Worker
actor。就像在现实生活中一样,你通常会要求经理组织一些要做的工作,然后经理会反过来决定哪些员工是工人