C++によるWindows開発---スレッドプールのキャンセルとクリーンアップ


マルチスレッドアプリケーションといえば、キャンセルとクリーンアップはかなり難しい問題です.
もしそうなら、ハンドルを安全に閉じることができますか?
どのスレッドがキャンセルされたかを考慮する必要がありますか?
さらに悪いことに、いくつかのマルチスレッドのApiは再入力されず、潜在的に性能が向上するが、開発者の複雑さも増加している.
最後の月のコラムのスレッドプール環境(msdn.microsoft.com/magazine/h 394144)を導入しました.この環境で許可される重要な機能は、グループをクリーンアップすることです.これは何ですか.ここに重点を置きます.クリーンアップグループは、すべての世界のキャンセルとクリーンアップの問題を解決しようとしないでください.スレッドプールのオブジェクトとコールバックを行い、管理を容易にし、必要に応じてキャンセルとパージの他のApiとリソースを間接的に簡素化します.
これまでuniqueの使用方法のみを表示してきました.handleクラステンプレートは、CloseThreadpoolWork関数を使用した作業オブジェクトを自動的に閉じます.(8月2011年列msdn.microsoft.com/magazine/h 335066の詳細を参照).しかし、この方法を使用するにはいくつかの制限があります.コールバックが保留または保留を取り消すかどうかを説明するには、まずWaitForThreadpoolWorkCallbackを呼び出す必要があります.これにより、2つの関数呼び出しのコールバックによって生成されたmultipliednumberオブジェクトがアプリケーションを使用しています.TrySubmitThreadpoolCallbackを使用する傾向がある場合は、このような機会を得ることができず、結果のコールバックをキャンセルまたは待機する方法を知りたいと思っています.もちろん、実際のアプリケーションはワークオブジェクトだけではない可能性があります.来月のコラムでは、i/oのタイマからコールバックを生成し、待機可能なオブジェクトの他のスレッドプールオブジェクトを生成するために導入します.キャンセルと整理を調整することは、すぐに悪夢になります.幸いなことに、これらの問題とより多くの内容を解決するためにグループを整理します.
CreateThreadpoolCleanupGroup関数は、クリーンアップグループオブジェクトを作成します.この関数が成功すると、グループオブジェクトのクリーンアップを示す不透明なポインタが返されます.失敗するとnullポインタ値が返され、GetLastError関数で詳細が表示されます.指定されたグループ・オブジェクトをクリーンアップします.CloseThreadpoolCleanupGroup関数は、スレッド・プールがオブジェクトを解放する可能性があることを示します.アクションに言及したことがありますが、スレッドプールAPIはパラメータを無効にすることを許さないことを強調する必要があります.CloseThreadpoolCleanupGroupまたは他のAPI関数を呼び出して、以前に閉じた無効なポインタまたは空のポインタ値を使用すると、アプリケーションがクラッシュします.これらはプログラマによって導入された欠陥であり、実行時に追加のチェックは必要ないはずです.2011年7月のコラムで導入したunique_handleクラステンプレート(msdn.microsoft.com/magazine/hh 288076)は、これらの詳細を担当して、特定のプロパティクラスのグループを整理します.

   
   
   
   
  1. struct cleanup_group_traits
  2. {
  3. static PTP_CLEANUP_GROUP invalid() throw()
  4. {
  5. return nullptr;
  6. }
  7. static void close(PTP_CLEANUP_GROUP value) throw()
  8. {
  9. CloseThreadpoolCleanupGroup(value);
  10. }
  11. };
  12. typedef unique_handle<PTP_CLEANUP_GROUP, cleanup_group_traits> cleanup_group;

typedef , :


   
   
   
   
  1. cleanup_group cg(CreateThreadpoolCleanupGroup());
  2. check_bool(cg);

, 。 , , , :


   
   
   
   
  1. environment e;
  2. SetThreadpoolCallbackCleanupGroup(e.get(), cg.get(), nullptr);

, 。 , 。

CreateThreadpoolWork :


   
   
   
   
  1. auto w = CreateThreadpoolWork(work_callback, nullptr, e.get());
  2. check_bool(nullptr != w);

unique_handle 。 , RAII 。

, CloseThreadpoolWork 。 , 。 : , CloseThreadpoolWork , 。

, 。 , 。CloseThreadpoolCleanupGroupMembers :


   
   
   
   
  1. bool cancel = ...
  2. CloseThreadpoolCleanupGroupMembers(cg.get(), cancel, nullptr);

, 。 , , 。 , ) 。 , 。

likened , 。 ) (STL) 。 CloseThreadpoolCleanupGroupMembers, 。 CloseThreadpoolCleanupGroup 。 , 。 — — , 。


   
   
   
   
  1. environment e;
  2. SetThreadpoolCallbackCleanupGroup(e.get(), cg.get(), nullptr);
  3. while (app is running)
  4. {
  5. SubmitThreadpoolWork(CreateThreadpoolWork(work_callback, nullptr, e.get()));
  6. // Rest of application.
  7. }
  8. CloseThreadpoolCleanupGroupMembers(cg.get(), true, nullptr);

, , 。

8 2011 , TrySubmitThreadpoolCallback , 。 API。 , , 。 TrySubmitThreadpoolCallback , , 。 , CloseThreadpoolCleanupGroupMembers 。


   
   
   
   
  1. environment e;
  2. SetThreadpoolCallbackCleanupGroup(e.get(), cg.get(), nullptr);
  3. while (app is running)
  4. {
  5. TrySubmitThreadpoolCallback(simple_callback, nullptr, e.get());
  6. // Rest of application.
  7. }
  8. CloseThreadpoolCleanupGroupMembers(cg.get(), true, nullptr);

TrySubmitThreadpoolCallback, forgive , 。 , 。 2011 7 。CloseThreadpoolCleanupGroupMembers , 。 , , , 
predictable 。 ,TrySubmitThreadpoolCallback , 。 , , 。

, 。 , 。

SetThreadpoolCallbackCleanupGroup , CloseThreadpoolCleanupGroupMembers 。 , 。


   
   
   
   
  1. void CALLBACK cleanup_callback(void * context, void * cleanup)
  2. {
  3. printf("cleanup_callback: context=%s cleanup=%s
    "
    , context, cleanup);
  4. }
  5. environment e;
  6. SetThreadpoolCallbackCleanupGroup(e.get(), cg.get(), cleanup_callback);

, CreateThreadpoolWork TrySubmitThreadpoolCallback , 。 CloseThreadpoolCleanupGroupMembers , 。


   
   
   
   
  1. void CALLBACK work_callback(PTP_CALLBACK_INSTANCE, void * context, PTP_WORK)
  2. {
  3. printf("work_callback: context=%s
    "
    , context);
  4. }
  5. void CALLBACK simple_callback(PTP_CALLBACK_INSTANCE, void * context)
  6. {
  7. printf("simple_callback: context=%s
    "
    , context);
  8. }
  9. SubmitThreadpoolWork(CreateThreadpoolWork(work_callback, "Cheetah", e.get()));
  10. SubmitThreadpoolWork(CreateThreadpoolWork(work_callback, "Leopard", e.get()));
  11. check_bool(TrySubmitThreadpoolCallback(simple_callback, "Meerkat", e.get()));

Meerkat , 。 , ?


   
   
   
   
  1. CloseThreadpoolCleanupGroupMembers(cg.get(), true, "Cleanup");

, :


          work_callback: context=Cheetah work_callback: context=Leopard simple_callback: context=Meerkat cleanup_callback: context=Cheetah cleanup=Cleanup cleanup_callback: context=Leopard cleanup=Cleanup
        

Windows API , , 。 , , , 。 TrySubmitThreadpoolCallback 。 CloseThreadpoolCleanupGroupMembers 。 , CloseThreadpoolCleanupGroupMembers 。 , TrySubmitThreadpoolCallback。

, , CloseThreadpoolCleanupGroupMembers , 。 — — , CloseThreadpoolCleanupGroupMembers — 、 。