我想知道.net API(BeginGetResponse、BeginRead 等)中现有的 I/O 绑定 APM 调用是使用线程池中的线程还是使用当前线程直到回调。我知道它一直“异步”到硬件/网卡。我也知道回调是在线程池上执行的。我的问题是: BeginGetResponse 的所有内容都在 Threadpool 上执行,或者直到等待 I/O 的内容都在当前线程上执行;然后其余的在线程池上执行。
我希望这个问题很清楚。我真的很想知道 BeginGetResponse 是如何在底层实现的。
我想知道.net API(BeginGetResponse、BeginRead 等)中现有的 I/O 绑定 APM 调用是使用线程池中的线程还是使用当前线程直到回调。我知道它一直“异步”到硬件/网卡。我也知道回调是在线程池上执行的。我的问题是: BeginGetResponse 的所有内容都在 Threadpool 上执行,或者直到等待 I/O 的内容都在当前线程上执行;然后其余的在线程池上执行。
我希望这个问题很清楚。我真的很想知道 BeginGetResponse 是如何在底层实现的。
APM 是更通用的机制。但是您所说的情况使用操作系统对I/O 完成端口的支持。一般的想法是你的主线程调用 BeginXxx() 方法。在后台,它调用ThreadPool.BindHandle(),它设置管道以使端口在 I/O 操作完成时自动启动 TP 线程。该线程调用您的回调方法。
核心思想是在 I/O 操作发生时没有线程在等待。
这支持 MessageQueue、FileStream、PipeStream、Socket、FileSystemWatcher、IpcChannel 和 SerialPort。
BeginXxx 在当前线程上执行。您可以使用例如 Reflector 轻松地为自己验证这一点。此外,有时回调也在当前线程上执行。一种情况是早期发生错误,另一种情况是实际异步 I/O 操作阻塞时——这种情况有时会发生,因为异步 I/O 不能保证不会阻塞。
使用工作池线程的 IAsyncResult 方法仅适用于某些任务。像 FileIO(不是目录枚举)、LDAP 查询(v2.0)、ADO .net 查询。如果您拥有它并且可以承受复杂性,请使用 APM。它们通常由 .net 人员构建,因为它需要一些复杂性。否则,如果您认为您会获得速度,请使用手工制作。使用显式线程可以为您提供更多控制。具体来说,您可以选择拥有前台线程,这将使您的应用程序在主线程从 Main 返回后保持“活动”。显式线程也可以指定它们的 COM 线程单元。一般规则是当你有工作项队列要做时使用线程池,当你有架构需要时使用显式线程。
许多操作使用IO 完成端口。
这意味着在等待操作时不使用线程。操作完成后,将在线程池线程上或使用其他一些同步上下文调用回调。