我不确定这是否与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个线程已经过去了?
答案 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
}