I / O

时间:2016-04-07 10:55:56

标签: windows sockets io threadpool

我不了解最新的Windows threadpool API的一部分。我需要帮助。

从文档中,将其用于I / O的配方(在我的情况下,用于SOCKET)可归纳如下:

  1. 调用CreateThreadpoolIo。
  2. 致电StartThreadpoolIo。你可以在那里找到这个警告:
      

    在对绑定到I / O完成对象的文件句柄启动每个异步I / O操作之前,必须调用此函数。如果不这样做,将导致线程池在完成时忽略I / O操作,并导致内存损坏。

  3. 调用文件句柄上的操作(例如,WSARecvFrom)。如果失败,请致电CancelThreadpoolIo。否则,在结果可用时处理结果。 WSARecvFrom,当异步使用时,会要求WSAOVERLAPPED(您必须事先创建),但不会将任何信息链接到之前对StartThreadpoolIo的调用。 CancelThreadpoolIo仅询问PTP_IO,但不会导致任何其他信息导出特定的异步操作。
  4. 重复步骤2和3。
  5. 调用CloseThreadpoolIo完成。你可以在那里找到这个警告:
      

    可能需要取消线程池I / O通知以防止内存泄漏。有关更多信息,请参阅CancelThreadpoolIo。

  6. 我通常需要它用于UDP,因此我努力在任何给定时间排队几个接收操作(异步WSARecvFrom操作已启动)。这样我就不必急于在回调函数的开头开始另一个接收操作,也不必同步访问接收缓冲区(我可以有一个池,每个都可以包含一个数据报,并重新发出当我完成处理每条消息时的接收操作;在此期间,其他排队的操作将使接收器保持忙碌状态。数据报是独立的,自包含的。我知道这种方法可能对TCP无效。

    StartThreadpoolIo / CancelThreadpoolIo在我看来问题的根源:StartThreadpoolIo和WSARecvFrom没有直接绑定(他们不共享任何参数)。所以:

    当您调用CancelThreadpoolIo时,框架如何知道取消哪个操作?它如何取消失败的操作而不取消任何待处理的操作?

    你可以说,"不要同时调用StartThreadpoolIo"。我可以在没有多个并发WSARecvFrom的情况下生活,但我不能在没有并发WSARecvFrom和WSASendTo的情况下生活。所以我认为无法同时进行多个异步操作可能不是API的设计方式。

    你可以说,"只调用一次StartThreadpoolIo,这足以注册回调;这是一个开/关过程"。但文件说:

      

    在启动文件句柄上的每个异步I / O操作之前,必须调用此函数...

    你可以说,"它取消了刚刚调用StartThreadpoolIo"的同一个线程启动的操作。但是在调用CloseThreadpoolIo的上下文中调用CancelThreadpoolIo的建议没有意义(我将从触发停止的线程调用CloseThreadpoolIo,这将完全独立于发出异步操作的线程;以及单个调用CancelThreadpoolIo可能不足以取消多个操作)。无论如何,无法从不同的线程触发取消是一个严重的限制。我知道CreateThreadpoolCleanupGroup的存在,但我的问题更为基础。我想了解这个API如何从根本上说是正确和有用的。

    您可以说"多次调用CreateThreadpoolIo,这样您就可以使用独立的PTP_IO来处理"。它不起作用。当我第二次调用CreateThreadpoolIo时,返回nullptr。

    我错了,或者这个API有尴尬吗?通常,其他异步API使用以下模式之一:

    1. 创建操作并接收句柄=>传递句柄的调用方法。
    2. 创建可重复使用的句柄=>调用方法(包括启动操作)传递句柄。
    3. 最新的Windows线程池API,其中句柄似乎是隐式的,或者有相同操作的多个句柄(TP_IO,WSAOVERLAPPED,StartThreadpoolIo)并且它们都没有明确地链接在一起,它们都不使用它们

      非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

  
    

当你调用CancelThreadpoolIo时,框架如何知道要取消哪个操作?它如何取消失败的操作     而不是任何待定的?

  

CancelThreadpoolIo()不取消IO。它与StartThreadpoolIo()相反。 StartThreadpoolIo()准备线程池以接受完成。如果线程池没有预期完成,它就不会等待它,因此你可能会错过它。如果线程池期望完成但完成没有发生,则线程池可能会浪费资源。

CancelThreadpoolIo()取消了StartThreadpoolIo()所做的任何事情。