我不确定这是否更多地与 akka.net 或 TPL 相关,但我将使用 actors 作为我的示例来澄清问题。
问题简而言之:有什么方法可以让 akka.net 一次触发比我实际拥有的 CPU 内核更多的线程?下面是示例代码和详细信息:
我目前使用的是配备 8 核处理器的笔记本电脑。假设我要创建 20 个 Actor :
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);
所有 Actor 在接收消息时所做的是以下伪造的长时间运行的进程:
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 个 Actor 的“向 Actor 发送消息”行。但是之后,当时间到了初始化时,发生的情况是一开始只创建了 8 个 actor。
然后,由于其他 Actor 都没有完成这项工作,恰好 1 秒后,另一个 Actor 被初始化(第 9 个)。一秒钟后,我们创建了第 10 个 actor 并开始了 Thread.Sleep 操作。
现在的问题是,有什么方法可以告诉 akka.net(或它下面的 TPL)我确定线程会为每个服务调用等待约 60 秒?以便一次触发所有 20 个线程,而不是一次启动 8 个,并且全部 20 个线程仅在 12 秒后才运行?
最佳答案
Akka actor 默认在 .Net ThreadPool 上运行。
您正在经历 ThreadPool 饥饿,其中所有可用线程都忙(每个 CPU 一个)。当它的所有线程都忙时,ThreadPool 每秒向其池中添加一个线程。
要“解决”您的问题,您可以使用 ThreadPool.SetMinThreads 增加最小线程数。但真正的解决办法是不要阻塞线程(也不要阻塞 actors)。
如果您的工作负载受 CPU 限制,那么并发运行更多的 actor 不会更快。
如果您的工作负载受 IO 限制,您应该异步调用它:
Receive<string>(msg =>
{
DoSomethingAsync(msg).PipeTo(Self);
}
Receive<Result>(msg =>
{
// Process the result
}
关于c# - 在 akka.net 中立即触发多个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35566093/