nik*_*ovn 5 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>());
}
Run Code Online (Sandbox Code Playgroud)
然后我将消息传递给所有这些:
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);
Run Code Online (Sandbox Code Playgroud)
所有演员都这样做,而接收消息的是以下假的长时间运行过程:
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);
Run Code Online (Sandbox Code Playgroud)
我在构造函数中也有这个代码,所以我知道实际创建actor的时间:
public ExampleActor()
{
Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay);
....
}
Run Code Online (Sandbox Code Playgroud)
所以现在当我运行应用程序时,我首先得到所有20个演员的"发送消息给演员"行 - 在同一毫秒内.但之后,当时间来自初始化时,会发生的事情是最初只创建了8个演员.
然后,因为没有其他演员完成这项工作,所以在1秒之后,另一个演员被初始化(第9个).再过一秒钟,我们创建了第10个actor并启动了Thread.Sleep操作.
现在的问题是,有没有办法告诉akka.net(或它下面的TPL)我确定线程将等待每个服务调用约60秒?这样所有20个线程一次被触发,而不是一次启动8个,并且仅在12秒后运行的完整20个线程已经过去了?
Akka Actor 默认在 .Net ThreadPool 上运行。
您正在经历线程池饥饿,其中所有可用线程都繁忙(每个 CPU 一个)。当所有线程都繁忙时,ThreadPool 每秒会向其池中添加一个线程。
要“解决”您的问题,您可以使用 ThreadPool.SetMinThreads 增加最小线程数。但真正的解决方法是不阻止线程(并且不阻止参与者)。
如果您的工作负载受 CPU 限制,那么同时运行更多参与者并不会加快速度。
如果您的工作负载受 IO 限制,则应该异步调用它:
Receive<string>(msg =>
{
DoSomethingAsync(msg).PipeTo(Self);
}
Receive<Result>(msg =>
{
// Process the result
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1221 次 |
| 最近记录: |