c# - 在 akka.net 中立即触发多个线程

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

我不确定这是否更多地与 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/

相关文章:

c# - Akka.net - 尝试测试重复的预定消息

c# - 自定义绑定(bind)的数据 GridView

c# - Azure WebJob 运行后更新 UI

c# - 为什么同步延续不再同步执行?

c# - 缺少非捕获 Task.Yield 迫使我使用 Task.Run,​​为什么要遵循它?

具有远程节点 : Disassociated exception 的 Akka (.net) 集群

java - Android 上 AKKA(最好是 2.4)的 JAR 文件(编译的 java 版本 1.6 - 不是 1.8)

c# - DotnetNuke 模块集成

c# - Entity Framework Core 两个对象作为主键

c# - 多个操作的并行化和结果的连接