WdfWorkItemEnqueue 関数 (wdfworkitem.h)

[KMDF と UMDF に適用]

WdfWorkItemEnqueue メソッドは、指定されたフレームワーク作業項目オブジェクトをシステムの作業項目キューに追加します。

構文

void WdfWorkItemEnqueue(
  [in] WDFWORKITEM WorkItem
);

パラメーター

[in] WorkItem

WdfWorkItemCreate の以前の呼び出しから取得されたフレームワーク作業項目オブジェクトへのハンドル。

戻り値

なし

解説

ドライバーが無効なオブジェクト ハンドルを提供すると、バグ チェックが発生します。

ドライバーが WdfWorkItemCreate を呼び出して作業項目を作成した後、ドライバーは WdfWorkItemEnqueue を呼び出して、作業項目をシステムの作業項目キューに追加する必要があります。 システム ワーカー スレッドは、その後、キューから作業項目を削除し、作業項目の EvtWorkItem コールバック関数を呼び出します。 作業項目は、キューに追加された順序で削除されます。

ドライバーは WdfWorkItemEnqueue を呼び出す前に、通常、作業項目オブジェクトのコンテキスト メモリを使用して作業項目に関する情報を格納します。 EvtWorkItem コールバック関数は、この情報を使用して、実行する必要がある操作を決定します。

バージョン 1.7 以降の KMDF では、ドライバーが作業項目オブジェクトを再利用する場合、システム ワーカー スレッドが作業項目をデキューし、その後ドライバーの EvtWorkItem コールバック関数を呼び出す前に、同じ作業項目に対して WdfWorkItemEnqueue を再度呼び出すことができます。 ただし、既に存在する場合、KMDF は作業項目をキューに追加しません。 したがって、 EvtWorkItem コールバック関数は、呼び出されるたびにキューに登録されたすべての作業を処理する必要があります。

ドライバーは、EvtWorkItem コールバック関数の実行中に WdfWorkItemEnqueue を呼び出して、別 作業項目をキューに入れることもできます。 2 番目の作業項目の EvtWorkItem コールバックは、最初の作業項目が完了する前に実行される場合もあります。

バージョン 1.7 より前のバージョンの KMDF では、ドライバーが作業項目オブジェクトを再利用する場合、システム ワーカー スレッドが作業項目をデキューし、EvtWorkItem コールバック関数を呼び出すまで、同じ作業項目に対して WdfWorkItemEnqueue を再度呼び出してはなりません。

作業項目の詳細については、「フレームワーク作業項目の 使用」を参照してください。

このセクションには、2 つの例が含まれています。 最初の例は、KMDF バージョン 1.7 以降のキューに作業項目を追加する方法を示しています。 2 番目の例は、バージョン 1.7 より前の KMDF バージョンのキューに作業項目を追加する方法を示しています

例 1: KMDF バージョン 1.7 以降

次のコード例では、作業項目オブジェクトのコンテキスト メモリへのポインターを返すローカル ルーチンを呼び出します。 この例では、オブジェクトのコンテキスト メモリに情報を設定し、 WdfWorkItemEnqueue を呼び出します。 ドライバーの EvtWorkItem コールバック関数は、後で作業項目オブジェクトから情報を取得します。

PMY_CONTEXT_TYPE context;

context = GetWorkItemContext(hWorkItem);
context->FdoData = FdoData;
context->Argument1 = Context1;
context->Argument2 = Context2;

WdfWorkItemEnqueue(hWorkItem);

ドライバーの EvtWorkItem コールバック関数には、次のコードが含まれています。

MyWorkItemCallback (
    IN WDFWORKITEM hWorkItem
    )
{
    PMY_CONTEXT_TYPE context;

    context = GetWorkItemContext(hWorkItem);

    //
    // Do work here.
    //
    ...
    //
    return;
}

例 2: 1.7 より前の KMDF バージョン

次のコード例では、作業項目オブジェクトのコンテキスト メモリへのポインターを返すローカル ルーチンを呼び出します。 この例では、オブジェクトのコンテキスト メモリ内の情報を設定し、状態変数を "busy" に設定してから、 WdfWorkItemEnqueue を呼び出します。 ドライバーの EvtWorkItem コールバック関数は、後で作業項目オブジェクトから情報を取得します。

typedef enum _WORKITEM_STATE {
    WORKITEM_STATE_FREE =0,
    WORKITEM_STATE_BUSY = 1
} WORKITEM_STATE;
...
PMY_CONTEXT_TYPE context;

context = GetWorkItemContext(hWorkItem);
context->FdoData = FdoData;
context->Argument1 = Context1;
context->Argument2 = Context2;

if (InterlockedCompareExchange(
                               (PLONG)&context->WorkItemState,
                               WORKITEM_STATE_BUSY,
                               WORKITEM_STATE_FREE
                               ) == WORKITEM_STATE_FREE) {
 WdfWorkItemEnqueue(hWorkItem);
}

ドライバーの EvtWorkItem コールバック関数には、次のコードが含まれています。 return ステートメントの直前に、ドライバーがオブジェクトを再度キューに入れるように、作業項目オブジェクトの状態変数を "free" に設定します。

MyWorkItemCallback (
    IN WDFWORKITEM hWorkItem
    )
{
    PMY_CONTEXT_TYPE context;
    LONG result;

    context = GetWorkItemContext(hWorkItem);

    //
    // Do work here.
    //
    ...
    //
    // Reset object state.
    //
    result = InterlockedExchange(
                                 (PLONG)&context->WorkItemState,
                                 WORKITEM_STATE_FREE
                                 );
    ASSERT(result == WORKITEM_STATE_BUSY);
    return;
}

要件

要件
対象プラットフォーム ユニバーサル
最小 KMDF バージョン 1.0
最小 UMDF バージョン 2.0
Header wdfworkitem.h (Wdf.h を含む)
Library Wdf01000.sys (KMDF);WUDFx02000.dll (UMDF)
IRQL <= DISPATCH_LEVEL
DDI コンプライアンス規則 DeferredRequestCompleted(kmdf)DriverCreate(kmdf)KmdfIrql(kmdf)KmdfIrql2(kmdf)、KmdfIrqlExplicit(kmdf)、 RequestCompleted(kmdf)RequestCompletedLocal(kmdf)

こちらもご覧ください

Evtworkitem

InterlockedCompareExchange

InterlockedExchange

WdfWorkItemCreate