【问题标题】:Asynchronous delegates operation clarification?异步委托操作说明?
【发布时间】:2013-03-12 16:20:11
【问题描述】:

我正在阅读 this question 并由 Hans 回答,但我仍然需要澄清。

阿法伊克,

异步方法的目的是允许许多任务在其上运行 线程少;而异步委托的目的是执行一个 任务与调用者并行。

但是关于这两个异步操作:

如果BeginInvoke立即返回给调用者(它使用异步委托),那么必须有其他线程实际完成这项工作并在何时发出信号它完成了。

那么使用 that 线程与常规线程池线程有什么区别? 我回答:只有那些线程池线程已经存在并等待运行的事实?

但是,当BeginInvoke 运行并立即返回时,实际上有人 else 已经完成了肮脏的工作(并且代码必须在正在处理的线程下运行。)所以必须有在某处创建线程(在 beginXXX 调用之后运行)

我错过了什么?

【问题讨论】:

标签: c# asynchronous .net-4.0


【解决方案1】:

Delegate.BeginInvoke 使用线程池线程,就像QueueUserWorkItem。不同之处在于它实现了 APM 模式,允许调用者使用WaitHandle 等待调用完成,并提供回调。

Begin/End 方法对(AKA 异步编程模型)可以在很多地方找到,并且完全由实现者来决定调用“开始”时会发生什么。很多情况下都会用到一个IO完成端口,这是一种非常高效的等待IO完成的方式。当 IO 完成时,一个线程池线程用于执行回调,但它取自线程池的不同部分(这就是为什么 Set{Min,Max}Threads 有两个数字。)

附带说明,在 .NET 4.5(甚至 4.0)中,使用 Tasks 实现异步要容易得多。许多类都增加了诸如“XXXTaskAsyc”之类的方法,这些方法返回一个Task 对象。

【讨论】:

  • Eli:你说当IO完成s时,使用线程池线程来执行回调但是让我们退后一步,在它完成之前并且仍在工作,它是否在线程池线程下工作?
  • 如果您使用 IO 完成端口,您将屈服于操作系统。所以不,在执行 IO 时您不会“浪费”线程池线程。
  • Eli 所以这是我的实际问题。我在 OS 线程中完成了工作。所以它是线程的创建。那么好处在哪里呢?只是它不是一个 threapool 线程?
  • 操作系统将工作卸载到实际的 IO 设备并在完成时中断您的进程。我建议您阅读 IO 完成端口:msdn.microsoft.com/en-us/library/aa365198
【解决方案2】:

看来您自己已经得到了答案:BeginInvoke 使用 Threadpool-thread 来完成这项工作。最后,这似乎与自己将工作项排队到线程池没有任何不同。唯一的事情是你所面临的更高层次的抽象。您实际上并不关心在代码中显式地排队和提供回调。
这已经看过了。见SO这里的想法。

【讨论】:

  • 例如,获取一个网页可能需要从开始到结束的几秒钟(因为连接可能很慢),但只消耗几分之一毫秒的 CPU 时间全部的。处理 HTTP 请求和响应不是计算密集型的。这意味着专用于处理单个客户端请求的服务器线程可能会花费 99% 的时间被阻塞所以你是在告诉我,仍然会有一个线程池(线程)在 99% 的时间内被阻塞?
  • 为什么是整个线程池?当然,如果线程等待数据或其他任何东西,它就会阻塞。不过,这不会阻塞整个线程池。
  • @RoyiNamir 好的,但这仍然是等待输入的线程的本质。如果它打算被阻止一段时间,那么就会发生这种情况。
  • 不,线程不需要一直阻塞。当然,这取决于实施。执行IO的时候可以使用completion ports,所以当你拿到一个TCP socket,你BeginSend当前线程立即yield,你可以在completion回调处继续写。
  • @EliArbel 当然,这些是特殊情况。但是如果你按照标准的方式来做,线程就会阻塞。
猜你喜欢
  • 2021-05-23
  • 1970-01-01
  • 2014-01-04
  • 2017-06-23
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2015-10-13
相关资源
最近更新 更多