【问题标题】:What's the point of using Tasks if I have to create my own STA Threads to run them in parallel?如果我必须创建自己的 STA 线程来并行运行它们,那么使用任务有什么意义?
【发布时间】:2017-11-04 00:46:13
【问题描述】:

我已经阅读和观看了很多关于为什么我应该使用任务而不是线程的 Microsoft 视频,这很有意义(我认为)。但是这个来自微软Parallel Programming with .NET 的博客让我很困惑。

我的理解是通过使用任务,我可以更好地利用多核并让这些任务并行运行。问题是我正在调用实例化一些 COM 对象的本机代码,因此我的任务必须在 STA 线程上运行。

在本文中,作者说要让任务在 STA 线程上运行,您必须从 STA 线程创建任务。他创建了一个 STA 线程并从中创建了 10 个任务,然后由于从一个线程中创建任务,他确定所有任务将按顺序运行。

等等……为什么?如果我必须创建自己的线程来让我的任务并行运行,那不是违背了目的吗?为什么它们不并行运行?

我错过了什么?

【问题讨论】:

  • 在这种情况下他是在谈论单核吗?那么所有线程都按顺序运行是有意义的。其实他是。查看线程数: var sta = new StaTaskScheduler(numberOfThreads:1);
  • 是和不是。使用任务通常是一种更清晰的抽象,并且 C# 在使用它们时具有一些额外的功能。但是,您实际上并不能保证它们并行运行 - 它们被放入队列中,并且它们等待被现有线程(或多或少)拾取。尽管您也不能真正保证本机线程并行运行,因为您依赖操作系统进行调度和上下文切换。不过,我想有人已经编写了本机任务调度程序,因此您也许可以使用现有的库。
  • 正如作者所说:“一般来说,最好避免使用 STA 对象”。
  • 使用任务而不是线程的一个论点是消除上下文切换。我在具有 2 个 CPU 的 VM 中运行,并且任务按顺序运行。除非我在那篇文章中使用该代码,然后它们在创建的多个线程上按顺序运行。那么性能提升在哪里?我没听懂。
  • @YuriS...当然...但也读到它对于 COM 对象是必要的。所以我别无选择。

标签: c# multithreading parallel-processing task-parallel-library taskscheduler


【解决方案1】:

如果我必须创建自己的线程来让我的任务并行运行,那不是违背了目的吗?为什么它们不并行运行?

具体到您的情况的问题是您正在与 单线程单元 (STA) COM 对象进行交互。 STA 表示它不是线程安全的。

如果不是所有 UI COM 对象(例如 Microsoft Office Ole Automation 中的任何东西),大多数(如果不是全部)在设计上或出于历史原因都不是线程安全的,并且必须从创建它们的线程中调用。所有此类方法调用都是通过 Windows 消息泵发送的,因此它们是序列化的。

如果您尝试从工作线程更新自己的 UI,也没有什么不同 - 您不能。

如果我必须创建自己的 STA 线程来并行运行任务,那么使用任务有什么意义?

  1. 根据那篇文章,您最终将创建自己的任务调度程序,而不仅仅是“创建我自己的...线程”。自定义任务调度器并不是一件坏事,TPL 在设计上允许这样做

  2. 如果 STA COM 对象都属于同一个进程,您将永远无法并行调用它们

结论

您似乎将这个 COM STA 问题归咎于 TPL,这有点不公平。无论您完全避免 TPL 并使用自己的线程,STA 线程问题都会持续存在;如果您尝试从 C++ 中调用 STA COM 对象;或通过 LAN 上的联网计算机使用 DCOM。

【讨论】:

  • 在文章中,第一个示例使用中没有使用 COM,但任务在一个线程上运行。您是否试图建议仅通过使它们成为 MTA 线程它们将并行运行?如果不是,您是否同意在此示例中使用任务没有性能提升?事实上,这只是额外的开销。
  • @tdemay 不,整篇文章都是关于 COM 的。为什么?因为他说的是纯粹是COM概念的STA。不,如果您创建一个 MTA 线程,而该线程又尝试调用 COM 对象,则它要么不响应,要么您的线程将因 [尝试从不属于创建的线程的线程调用对象]而崩溃
  • @tdemay "...您是否同意使用任务没有性能提升..." - 尝试使用分布式计算也没有性能提升,就像说 DCOM 调用完全相同的对象。在这里,DCOM 可以被认为是对线程的类比。然而,最终所有调用都在目标进程中序列化。就像尝试更新 GUI 控件一样,最终一次只能更新一件事。 STA COM 也不例外。尝试任何诡计都不会让它变得更快
  • 你没有回答我想问的问题。暂时忘记 COM。您是说任务从 STA 线程按顺序运行,而从 MTA 线程并行运行?如果这就是你所说的,那么我不明白这篇文章的重点。为什么要在 STA 线程中使用任务?如果这不是您要说的,那么我不明白如何使用任务代替线程进行并行计算。
  • @tdemay 简而言之,是的,将Task 与 STA COM 一起使用完全是浪费时间。我相信使用Task 一次只能运行一个任务是愚蠢的,无论它是否是COM。我相信您链接到的那篇文章可能更好地用作如何制作自己的任务调度程序,但是这样做一次只能运行一个任务(如在 COM STA 中)是荒谬的。如果你问我,这是一个 MS 右手不知道左手在做什么的例子,或者是一种极端聪明的练习,没有任何意义。
猜你喜欢
  • 2011-08-23
  • 2011-03-06
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多