【问题标题】:Akka.net actors in STASTA 中的 Akka.net 演员
【发布时间】:2015-05-10 11:57:10
【问题描述】:

我需要将数千个不同格式的 ms office 文档转换为一种通用格式。为了让事情变得更快,我会使用 akka.net 来并行化它。 WordSaveAsActor 应该:

  • 在单线程 Appartment 中运行
  • 保存 Word 应用程序实例
  • 在此实例上进行 COM 调用,例如 SaveAs(..),其路径来自多个并行线程接收到的消息
  • 在任何崩溃时自行重启

是否可以在 STA 中运行 akka.net actor?如果我以这种方式使用 akka.net,有什么顾虑吗?

【问题讨论】:

  • Word 不太关心您的图书馆。它的互操作接口是单线程的,您从工作线程进行的任何调用都会自动编组到拥有 Application 对象的线程。它根本不会更快,它会更慢。您最多可以在不同的工作人员中处理不同的文档,每个工作人员都拥有自己的应用程序。这会很快停止缩放,Word 是一个非常繁重的过程。
  • 你不是说10000字的应用实例吗?如果我只发送路径,为什么会更慢?即使使用 async/await 而不是 BackgroundWorker 并寻找更好的解决方案,我也会遇到奇怪的效果和崩溃。

标签: c# com ms-word sta akka.net


【解决方案1】:

简短的回答是“是的,您可以使用 Akka.NET 做到这一点”

正如汉斯在评论中指出的那样:

Word 不太关心您的库。它的互操作接口是单线程的,您从工作线程进行的任何调用都会自动编组到拥有 Application 对象的线程。

您可以使用 Akka.NET 中的调度程序对参与者的并发需求进行一些控制 - 您可以read about different types of Akka.NET dispatchers and how they work in our Akka.NET Bootcamp Lesson 2.1

在你的情况下,我建议你这样做:

  1. 在 STA 线程上创建 WordSaveAsActor 并将其配置为使用 Akka.NET 中的 CurrentSynchronizationContextDispatcher,您可以通过配置来完成:

var wordActor = MyActorSystem.ActorOf(Props.Create(() => new WordSaveAsActor(...)).WithDispatcher("akka.actor.synchronized-dispatcher"))

此参与者处理的所有消息都将在 STA 线程上自动完成。我们在其他 STA 环境中使用这种技术,例如 Windows 窗体 UI,它极大地简化了一切。

  1. 在使用默认调度程序(CLR 线程池)的其他参与者上执行不需要 Word 的 COM 组件的所有其他工作。这可能包括任何文件复制、打开、移动等。当您需要发送数据时从 word 接收或接收数据,您可以让这些参与者将消息传递给您的 WordSaveAsActor

正如 Hans 所指出的,除非您并行运行多个 Word 实例,否则您实际上一次只能利用其 COM API 执行一项操作。因此,为了利用 Akka.NET 的并行性,您需要找到一种方法来使用多个参与者来并行化不需要 Word 的操作部分。

【讨论】:

  • 非常感谢您的详细解释!我在 github 上关注你的积极进展。现在只完成Bootcamp Unit 1 :) 将练习移植到 F#,这使得它们更加简单!我将运行一两个单词演员,这仍然是一个瓶颈。我想将字符串传递给演员的开销比在后台访问文件系统的繁重字操作要便宜得多,不是吗?
  • 向演员传递字符串非常便宜 - 我们的 PingPong 基准测试可以在 8 核开发机器上每秒处理 6000 万条消息。
猜你喜欢
  • 2014-09-30
  • 1970-01-01
  • 2015-02-22
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-03
  • 2017-02-15
相关资源
最近更新 更多