立刻在akka.net中发起多个线程

时间:2016-02-22 23:39:24

标签: c# task-parallel-library akka.net

我不确定这是否与akka.net或TPL有关,但我会用演员来说明这个问题。

问题简而言之:有没有办法告诉akka.net一次触发更多线程而不是实际拥有CPU内核?以下是示例代码和详细信息:

我目前正在使用配备8核处理器的笔记本电脑。所以我要说我创造了20个演员:

for (int i = 0; i < 20; i++)
{
    actorList.Add(system.ActorOf<ExampleActor>());
}

然后我将消息传递给所有人:

actorList[0].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 1\t" + DateTime.Now.TimeOfDay);
actorList[1].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 2\t" + DateTime.Now.TimeOfDay);
...
actorList[19].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 20\t" + DateTime.Now.TimeOfDay);

所有演员都在接收消息的同时执行以下虚假长时间运行过程:

Console.WriteLine("Accessing slow service\t" + DateTime.Now.TimeOfDay
     + "\t" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000);
Console.WriteLine("Service call was successful\t" + DateTime.Now.TimeOfDay
     + "\t" + Thread.CurrentThread.ManagedThreadId);

我的构造函数中也有这个代码,所以我知道实际创建actor的时间是什么:

public ExampleActor()
{
    Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay);
    ....
}

所以现在当我运行应用程序时,我首先得到所有20个演员的“发送消息给演员”行 - 在同一毫秒内。但之后,当时间来自初始化时,会发生的事情是最初只创建了8个演员。

然后,因为没有其他演员完成这项工作,所以在1秒之后,另一个演员被初始化(第9个)。再过一秒钟,我们创建了第10个actor并启动了Thread.Sleep操作。

现在的问题是,有没有办法告诉akka.net(或它下面的TPL)我确定线程会等待约60秒进行每次服务调用?这样所有20个线程一次被触发,而不是一次启动8个,并且仅在12秒后运行的完整20个线程已经过去了?

1 个答案:

答案 0 :(得分:3)

默认情况下,Akka演员在.Net ThreadPool上运行。

您正在遇到ThreadPool饥饿,其中所有可用线程都忙(每个CPU一个)。当其所有线程都忙时,ThreadPool每秒向其池中再添加一个线程。

To&#34;解决&#34;您可以使用ThreadPool.SetMinThreads增加最小线程数。但真正的解决方法是不阻止线程(而不是阻止线程)。

如果您的工作负载受CPU限制,那么让更多的actor同时运行会更快。

如果您的工作负载是IO绑定的,您应该异步调用它:

Receive<string>(msg =>
{
    DoSomethingAsync(msg).PipeTo(Self);
}

Receive<Result>(msg =>
{
   // Process the result
}