Отмена запланированных элементов work/io/timer в пуле потоков WIN32

Я играл с API-интерфейсом пула потоков Windows (новым?). Я использовал пример из раздела Использование функций пула потоков и я внимательно изучил API в MSDN. Что-то я не понимаю в группах очистки.

При вызове SetThreadpoolCallbackCleanupGroup() третий параметр описывается как

Обратный вызов очистки, который будет вызываться, если группа очистки отменяется до освобождения связанного объекта. Функция вызывается при вызове CloseThreadpoolCleanupGroupMembers().

Если я правильно понимаю, это означает, что вы можете отменить ожидающие элементы work/io/timer и попросить его вызвать функцию обратного вызова очистки для каждого из этих объектов вместо исходной очереди work/io/timer обратный вызов элемента. Это звучит круто, и я хотел бы использовать это.

К сожалению, тип PTP_CLEANUP_GROUP_CANCEL_CALLBACK, используемый для рассматриваемого обратного вызова, не задокументирован в MSDN, и рассматриваемый пример не использует эту функцию.

Взяв закон в свои руки, я проследил определение до WinNT.h и обнаружил следующее.

typedef VOID (NTAPI *PTP_CLEANUP_GROUP_CANCEL_CALLBACK)(
    __inout_opt PVOID ObjectContext,
    __inout_opt PVOID CleanupContext
    );

Если убрать лишнее из этой забавно выглядящей декларации, вы получите:

typedef void ( __stdcall * PTP_CLEANUP_GROUP_CANCEL_CALLBACK )
    ( void* ObjectContext, void* CleanupContext );

Вопрос. Если вам придется сделать обоснованное предположение, что, по вашему мнению, означают ObjectContext и CleanupContext?

Мое первое предположение состоит в том, что CleanupContext — это то, что вы указываете в момент запуска очистки: таким образом, 3-й параметр для CloseThreadpoolCleanupGroupMembers(). Я почти уверен, что это предположение верно, потому что вызовы API напрямую связаны.

Мое второе предположение заключается в том, что ObjectContext — это то, что вы указываете в момент отправки элемента work/io/timer: это второй параметр для CreateThreadpoolWork() и др. Я совершенно не уверен, что это так.

Может ли кто-нибудь подтвердить, что эти догадки верны? Кто-нибудь использовал эту функцию раньше?


person André Caron    schedule 18.11.2010    source источник


Ответы (1)


Необязательный обратный вызов очистки, указанный с помощью функции SetThreadpoolCallbackCleanupGroup, вызывается для каждого объекта, связанного с той же средой обратного вызова, которая еще не была закрыта к моменту вызова CloseThreadpoolCleanupGroupMembers. Первый параметр обратного вызова, контекст объекта, представляет собой значение параметра void*, которое вы указываете при использовании функций TrySubmitThreadpoolCallback, CreateThreadpoolWork и т. д. Второй параметр обратного вызова, контекст очистки, представляет собой значение параметра void*, которое вы указываете при использовании функции CloseThreadpoolCleanupGroupMembers.

Важно помнить, что вызов обратного вызова очистки для конкретного объекта не зависит от того, есть ли у этого объекта ожидающие выполнения обратные вызовы. Он вызывается только для объектов, которые еще не закрыты. Другими словами, вполне возможно, что обратный вызов объекта вызывается, а затем для этого же объекта вызывается обратный вызов очистки.

Если, например, вы создаете рабочий объект с помощью функции CreateThreadpoolWork и не можете вызвать функцию CloseThreadpoolWork до вызова CloseThreadpoolCleanupGroupMembers, то для этого объекта будет вызван обратный вызов очистки, даже если обратный вызов объекта уже был выполнен. Отсутствие вызова CloseThreadpoolWork не является ошибкой, так как CloseThreadpoolCleanupGroupMembers закроет все объекты, связанные с группой очистки.

Еще один поворот, на который следует обратить внимание, — это использование функции TrySubmitThreadpoolCallback. Это более простая версия CreateThreadpoolWork, в которой вам не нужно думать о создании, отправке и закрытии рабочего объекта. Хитрость заключается в том, что пул потоков автоматически закрывает рабочий объект после выполнения его обратного вызова. Это означает, что обратный вызов очистки будет вызываться для этого объекта только в том случае, если его обратный вызов все еще ожидает обработки, и вы указываете TRUE при вызове CloseThreadpoolCleanupGroupMembers для отмены любых ожидающих обратных вызовов.

person Kenny Kerr    schedule 19.11.2010
comment
Спасибо! Простой тест, который я провел вчера после публикации вопроса, подтвердил мои догадки об указателях, но я рад, что дождался вашего ответа. Я неправильно понял часть документации, относящейся к созданию/отправке/закрытию рабочих объектов, и мне было интересно, почему очистка была вызвана для всех моих рабочих объектов. - person André Caron; 19.11.2010