Akka.net actors in STA

2019-04-14 14:07发布

问题:

I need to convert thousands of ms office documents in different formats into one common format. To get things faster i would parallelize it using akka.net for. The WordSaveAsActor should:

  • run in Single-Threaded Appartment
  • hold the Word Application instance
  • make COM calls on this instance, like SaveAs(..) with paths from received messages from multiple parallel threads
  • restart itself by any crash

Is it even possible to run akka.net actor in STA? Is there any concerns if I use the akka.net this way?

回答1:

The short answer is "yes, you can do this with Akka.NET"

As Hans points out in his comment:

Word doesn't care much about your library. Its interop interface is single-threaded, any call you make from a worker thread is automatically marshaled to the thread that owns the Application object.

You can use the dispatchers in Akka.NET to exercise some control over your actors' concurrency needs - you can read about different types of Akka.NET dispatchers and how they work in our Akka.NET Bootcamp Lesson 2.1.

In your case, here's what I'd recommend you do:

  1. Create your WordSaveAsActor on the STA thread and configure it to use the CurrentSynchronizationContextDispatcher in Akka.NET, which you can do via configuration:

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

All messages this actor processes will be done automatically on the STA thread. We use this technique in other STA environments, such as Windows Forms UI, and it greatly simplifies everything.

  1. Do all of the other work that doesn't require Word's COM component on other actors that use the default dispatcher (CLR threadpool.) This might include any file copy, open, move, etc.. When you need to send data to or receive data from word, you can have these actors pass messages to your WordSaveAsActor.

As Hans points out, unless you run multiple instances of Word in parallel you can't really do more than one operation at a time leveraging its COM API. So in order to take advantage of Akka.NET's parallelism you'll need to find a way to use multiple actors to parallelize the parts of your operation that don't require Word.