Отмена запланированных элементов работы / ввода-вывода / таймера в пуле потоков WIN32 - PullRequest
1 голос
/ 19 ноября 2010

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

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

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

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

К сожалению, тип 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() и др. Я абсолютно не уверен, что это так.

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

1 Ответ

2 голосов
/ 19 ноября 2010

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

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

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

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

...