【问题标题】:Regarding various way of calling a method [closed]关于调用方法的各种方式[关闭]
【发布时间】:2013-04-23 14:55:54
【问题描述】:

我很少使用线程、后台工作程序等,但从未尝试知道我们应该何时使用哪个以及每种技术在内部如何工作。所以在这里我问几个关于线程、异步调用方法、后台工作者或 TPL 的问题。我在这里道歉,我问了几个问题。我的要求是请阅读并详细回答。

  1. 当我们运行我们的应用程序时,应用程序会从一个称为主线程的线程开始。 GUI 相关控件是在另一个线程上创建的,我听说了多远……是真的吗?是否为 GUI 创建了任何线程?

  2. 当我们调用少数方法时,所有方法调用都是按顺序发生的,这意味着一个方法调用stand & end,然后下一个方法将启动,一切都发生在主线程中。这就是主线程被阻塞的原因。如果我们不想阻塞主线程,那么我们总是喜欢在另一个线程上异步运行方法。异步调用任何方法是否意味着在单独的线程上执行方法?如果不是,这是否意味着异步调用在同一线程中执行而不阻塞主线程的任何方法?如果是,那怎么可能。请详细解释。

  3. 当我们异步调用任何不阻塞主线程的方法时实际发生了什么?我需要知道幕后发生了什么。

  4. 通过thread.start调用方法和异步调用方法有什么区别?

  5. 后台工作者在同一个主线程或单独线程中异步执行方法?

  6. 当我们使用 thread.start 调用方法时,我如何指定回调,当我的方法完成时,将发生回调并让我知道该方法完成。我尝试使用 thread.start 找到这样的示例,但没有找到。所以帮我用示例代码来做吧。

  7. 任务并行库的主要目标是什么。 TPL 是否在主线程或单独线程中执行任何方法?

我们可以使用 thread.start 或后台工作程序或异步调用任何方法来解决我们的目的,那么有什么额外的东西给了人们使用它的 TPL?

【问题讨论】:

  • 我正要回答,但我发现自己在重复自己。对 BackgroundWork 类进行一些研究,然后回来将您的问题修改为一个问题。如果您研究异步线程和同步线程之间的区别,那么每个问题都可以自己回答。我指出这没有建设性,因为您有 7 个不同的问题,而且大多数问题都非常广泛。
  • 你应该每个问题问一个问题,而不是一个问题 7 个问题。正如 Ramhound 所说,其中一些问题要么相同,要么可以合并为一个问题,但其中一些问题不同,应该在他们自己的问题中。

标签: c# task-parallel-library backgroundworker threadpool


【解决方案1】:

您的 GUI 线程与您的应用程序启动时的威胁是同一线程。默认情况下,您的应用程序只是一个线程(好吧......在后台是多个线程,但是那些处理一些 .NET 的东西,比如垃圾收集,你不需要担心)。

除了主线程之外,还有多个线程机制。基本上都使用相同的东西:Thread 类。所以是的,所有其他线程操作都不会在主线程上运行。

每个线程机制都有优点和缺点:

线程类
线程类是它们的基础。您可以启动它、加入(等到它完成)和中止它(Abort 已弃用,不推荐使用它)。创建一个新线程相对需要很多时间(在我的机器上 +/- 5 毫秒)。它不提供任何其他同步机制作为回调。你必须自己写。

线程池
因为线程的创建速度非常慢,所以 .NET 有一个线程池。线程池为异步操作做好准备。当异步操作排队时,线程池将其拾取并将其分配给已创建的空闲线程。线程将执行该操作。您可以使用ThreadPool.QueueUserWorkItem 对操作进行排队。回调是可能的。 TreadPool 应该只用于快速操作。 I/O 操作可能会占用大量时间,这可能会阻塞其他排队的操作。

异步调用
.NET 有很多不同的异步调用,比如委托InvokeAsync。大多数这些操作都被推入 ThreadPool 的队列中,因此所有这些方法也都支持它。所以非常方便。大多数 I/O 操作(如 (StreamReader.BeginRead))在新创建的线程上执行。

BackgroundWorker
BackgroundWorker 还使用 ThreadPool 来处理它的所有操作。

平行
Parallel 类随 .NET 框架 4.0 一起提供。它的创建是为了使(大型)集合的操作更容易。需要对集合内的所有项目执行的所有操作都分为几个线程(在 TreadPool 上),从而允许将工作负载分配到多核处理器的所有内核上。

【讨论】:

  • “所有这些操作都被推入 ThreadPool 的队列中”——实际上并非所有 I/O 方法都如此。如果可能,I/O 异步调用将使用 I/O 完成端口工具,这意味着它们根本不会消耗线程。
  • 另外,值得注意的是 Thread.Abort() 已弃用,不应使用。当线程中止时,调用堆栈中的finally 块不会运行。这会产生非常严重的后果,例如在拥有监视器时中止的线程(例如在lock 块中)不会释放监视器,从而使对象永久锁定。
  • @cdhowie:关于 I/O 操作,您是对的。我更新了我的答案。谢谢你的现场。
  • @cdhowie:是的,使用 Abort 有一些非常令人讨厌的副作用 :)。我以前曾为此挣扎过。但是finally 块以任何方式被调用(查看:msdn.microsoft.com/en-us/library/ty8d3wta.aspx)。唯一的缺点是错过了具有特定异常的 catch 块,因为 ThreadAbortException 覆盖了其他“未决”异常。
  • 啊,是的,问题是如果中止操作发生在监视器获取和try块的入口之间。 (Interrupt() 没有这个问题,因为 ThreadInterruptedException 仅从某些点抛出,例如阻塞 I/O。)
猜你喜欢
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
  • 2013-12-26
  • 1970-01-01
  • 2013-02-23
  • 2016-06-20
  • 2014-10-18
  • 1970-01-01
相关资源
最近更新 更多