.NET 4任务并行库可以使用COM对象吗?

这是“这是可能的,如果是这样,你能给我一个快速的例子,因为我找不到一个在线?” 有种问题。

我有许多完全独立的(即“尴尬的并行”)进程,我想使用C#使用.NET Framework 4中的任务并行库并行运行。 其中一些过程需要使用可通过COM / OLE自动化访问的软件。

具体来说,有一个Parallel.Foreach()循环,它将项目列表中的任务分开,基本上调用了Parallel.Foreach中的一个不同的函数来处理处理(因此其中一些函数使用COM库工作)。

这可能吗? 谢谢。


在TPL中使用COM对象是100%的可能。 确实,默认情况下,TPL将使用标准.NET ThreadPool,TPL通过TaskScheduler类具有扩展点,使您可以提供自己的调度程序,该调度程序可以将工作分派给您创建的线程。

在使用COM对象的情况下,首先需要知道COM类是否需要STA线程或MTA线程。 如果MTA线程,那么没有什么特别的需要完成,因为COM类已经可以从任何随机线程中使用。 不幸的是,大多数经典的COM对象都倾向于依赖于STA线程,这就是当你需要使用自定义的TaskScheduler所以你使用它的.NET线程已经被初始化为STA兼容线程。

虽然TaskSchedulers并不是完全无关紧要的,但如果您对线程有基本的了解,那么编写它们也不是很难。 幸运的是,ParallelExtensions Extras库已经提供了一个StaTaskScheduler类,所以你甚至不需要自己写任何东西。 PFX团队在这里有一篇很棒的博客文章,讨论StaTaskScheduler类的实现和一些用例。

但基本上,您需要将一个新的StaTaskScheduler初始化为某个类中的某个静态的静态文件,然后启动您的Tasks指定它们由该实例调度。 这看起来像这样:

// Create a static instance of the scheduler specifying some max number of threads
private static readonly StaTaskScheduler MyStaTaskScheduler = new StaTaskScheduler(4);

....

// Then specify the scheduler when starting tasks that need STA threading
Task.TaskFactory.StartNew(
() =>
{
    MyComObject myComObject = new MyComObject();

    myComObject.DoSomething();

    // ... etc ...
},
CancellationToken.None,
TaskCreationOptions.None,
MyStaTaskScheduler);

这可能是可能的,但它也可能不起作用。

许多COM对象需要特定的公寓线程。 当你使用Parallel.For / ForEach时,你运行的是.NET ThreadPool,它没有公寓线程设置。 这可能工作,并且可以用于某些COM对象,但也可能导致难以追踪的崩溃和奇怪的COM异常。


一些额外的信息,我还没有核实,但这可能会有所帮助。 默认任务调度程序将使用当前线程完成一些工作,然后根据需要从线程池中添加其他线程。

如果在执行Parallel.ForEach时共享COM对象,这可能会导致问题。 例如,假设您的主线程是STA。 你实例化COM对象,并使用Parallel.ForEach来完成一些工作,每个线程都尝试访问先前实例化的COM对象。 我怀疑它会中断,初步测试似乎支持了这一点。 在这种情况下,我看到至少有几个选项:

  • 假设COM对象支持MTA,请让调用线程使用MTA。 但是这可能不是其他原因的选择。 例如,如果应用程序是Windows窗体应用程序,我相信Main()需要具有STAThread属性。
  • 使用替代任务调度程序,例如Drew提到的StaTaskScheduler。 您可以拥有所有STA线程或使用不使用调用线程并运行所有MTA线程的调度程序。
  • 链接地址: http://www.djcxy.com/p/50151.html

    上一篇: Can the .NET 4 Task Parallel Library use COM objects?

    下一篇: Java regular expression offers any performance benefit?