2010-11-18 8 views
1

Ich habe mit Windows (neu?) Thread Pool API gespielt. Ich habe das Beispiel in der Using the Thread Pool Functions durchgegangen und habe mir die API auf MSDN gründlich angeschaut. Es gibt etwas, was ich über Aufräumgruppen nicht verstehe.Geplante Arbeit/io/Timer-Elemente im WIN32-Thread-Pool abbrechen

Wenn die SetThreadpoolCallbackCleanupGroup() Aufruf wird der dritte Parameter als

beschrieben

Der Bereinigungs Rückruf aufgerufen werden, wenn das cleanup Gruppenobjekt vor dem zugehörige abgebrochen wird freigegeben. Die Funktion wird aufgerufen, wenn Sie CloseThreadpoolCleanupGroupMembers() aufrufen.

Wenn mein Verständnis richtig ist, die Mittel, die Sie stornieren Arbeit/io/Timer-Produkte anhängig und fordert diese auf die Bereinigung Callback-Funktion auf jedes dieser Objekte aufzurufen statt der ursprünglich Warteschlange Arbeit/io/Rückruf des Timer-Elements. Das klingt cool und ich würde es gerne benutzen.

Leider ist der PTP_CLEANUP_GROUP_CANCEL_CALLBACK Typ, der für den betreffenden Rückruf verwendet wird, nicht auf MSDN dokumentiert, und das betreffende Beispiel verwendet diese Funktion nicht.

Indem ich das Gesetz in meine eigenen Hände nehme, habe ich die Definition auf WinNT.h zurückverfolgt und folgendes gefunden.

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

die cruft auf diesem lustigen suchen Erklärung bekommt man ausbauen:

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

Frage: Wenn Sie eine Vermutung nehmen müsste, was denken Sie ObjectContext und CleanupContext beziehen sich auf?

Meine erste Vermutung ist, dass CleanupContext ist, was Sie in dem Moment angeben, wenn Sie Bereinigung initiieren: also der 3. Parameter zu CloseThreadpoolCleanupGroupMembers(). Ich bin ziemlich zuversichtlich, dass diese Vermutung richtig ist, weil die API-Aufrufe so direkt verwandt sind.

Meine zweite Vermutung ist, dass ObjectContext ist, was Sie in dem Moment angeben, in dem Sie die Arbeit/io/Timer-Artikel senden: Dies ist der zweite Parameter zu CreateThreadpoolWork() et al. Ich bin mir absolut nicht sicher, dass dies der Fall ist.

Kann jemand bestätigen, dass diese Vermutungen korrekt sind? Hat jemand diese Funktion schon einmal benutzt?

Antwort

2

Der optionale Bereinigungsrückruf, den Sie mit der Funktion SetThreadpoolCallbackCleanupGroup angeben, wird für jedes Objekt aufgerufen, das derselben Rückrufumgebung zugeordnet ist, die zum Zeitpunkt des Aufrufs von CloseThreadpoolCleanupGroupMembers noch nicht geschlossen wurde. Der erste Parameter des Callbacks, der Objektkontext, ist der Wert des void * -Parameters, den Sie angeben, wenn Sie die Funktionen TrySubmitThreadpoolCallback, CreateThreadpoolWork usw. verwenden. Der zweite Parameter des Rückrufs, der Bereinigungskontext, ist der Wert des void * -Parameters, den Sie angeben, wenn Sie die CloseThreadpoolCleanupGroupMembers-Funktion verwenden.

Die wichtige Sache zu erinnern ist, dass, ob der Bereinigungsrückruf für ein bestimmtes Objekt aufgerufen wird, nicht davon abhängig ist, ob dieses Objekt ausstehende Rückrufe hat oder nicht. Es wird nur für Objekte aufgerufen, die noch nicht geschlossen sind. Mit anderen Worten, es ist durchaus möglich, dass der Callback des Objekts aufgerufen wird und dann der Cleanup-Callback für dasselbe Objekt aufgerufen wird.

Wenn Sie beispielsweise ein Arbeitsobjekt mit der CreateThreadpoolWork-Funktion erstellen und die CloseThreadpoolWork-Funktion vor dem Aufruf von CloseThreadpoolCleanupGroupMembers nicht aufrufen, wird der Bereinigungsrückruf für dieses Objekt aufgerufen, auch wenn der Rückruf des Objekts bereits ausgeführt wurde. Der Aufruf von CloseThreadpoolWork ist kein Fehler, da CloseThreadpoolCleanupGroupMembers alle Objekte schließt, die der Bereinigungsgruppe zugeordnet sind.

Eine weitere Wendung, auf die Sie achten sollten, ist die TrySubmitThreadpoolCallback-Funktion. Dies ist eine einfachere Version von CreateThreadpoolWork, da Sie nicht über das Erstellen, Senden und Schließen des Arbeitsobjekts nachdenken müssen. Der Trick besteht darin, dass der Thread-Pool das Arbeitsobjekt automatisch schließt, sobald sein Callback ausgeführt wurde. Dies bedeutet, dass der Bereinigungsrückruf nur für dieses Objekt aufgerufen wird, wenn sein Rückruf noch aussteht und Sie TRUE angeben, wenn Sie CloseThreadpoolCleanupGroupMembers aufrufen, um ausstehende Rückrufe abzubrechen.

+0

Danke! Ein einfacher Test, den ich gestern durchgeführt habe, nachdem ich die Frage gepostet habe, bestätigte meine Vermutungen über die Hinweise, aber ich bin froh, dass ich auf deine Antwort gewartet habe. Ich habe einige der Dokumentationen in Bezug auf das Erstellen/Senden/Schließen von Arbeitsobjekten falsch verstanden und mich gefragt, warum die Bereinigung für * alle * meine Arbeitsobjekte aufgerufen wurde. –