Функция WdfWorkItemEnqueue (wdfworkitem.h)

[Применимо к KMDF и UMDF]

Метод WdfWorkItemEnqueue добавляет указанный объект рабочего элемента платформы в очередь рабочих элементов системы.

Синтаксис

void WdfWorkItemEnqueue(
  [in] WDFWORKITEM WorkItem
);

Параметры

[in] WorkItem

Дескриптор объекта рабочего элемента платформы, полученный при предыдущем вызове WdfWorkItemCreate.

Возвращаемое значение

None

Remarks

Ошибка проверка возникает, если драйвер предоставляет недопустимый дескриптор объекта.

После вызова WdfWorkItemCreate для создания рабочего элемента драйвер должен вызвать WdfWorkItemEnqueue , чтобы добавить рабочий элемент в очередь рабочих элементов системы. Системный рабочий поток впоследствии удаляет рабочий элемент из очереди и вызывает функцию обратного вызова EvtWorkItem рабочего элемента. Система удаляет рабочие элементы в том порядке, в который они были добавлены в очередь.

Перед вызовом WdfWorkItemEnqueue драйверы обычно используют контекстную память объекта рабочего элемента для хранения сведений о рабочем элементе. Функция обратного вызова EvtWorkItem использует эти сведения для определения операции, которую она должна выполнить.

В kmdf версии 1.7 и более поздних версиях, если драйвер повторно использует свои объекты рабочих элементов, драйвер может снова вызвать WdfWorkItemEnqueue для того же рабочего элемента, прежде чем системный рабочий поток вывел рабочий элемент из очереди, а затем вызовет функцию обратного вызова EvtWorkItem драйвера. Однако KMDF не добавит рабочий элемент в очередь, если он уже существует. Поэтому функция обратного вызова EvtWorkItem должна обрабатывать все работы в очереди при каждом вызове.

Драйвер также может вызывать WdfWorkItemEnqueue во время выполнения функции обратного вызова EvtWorkItem для постановки в очередь другого рабочего элемента. Обратный вызов EvtWorkItem второго рабочего элемента может даже выполняться до завершения первого.

В версиях KMDF, предшествующих версии 1.7, если драйвер повторно использует свои объекты рабочих элементов, он не должен повторно вызывать WdfWorkItemEnqueue для того же рабочего элемента, пока системный рабочий поток не вывел рабочий элемент из очереди и не вызовет его функцию обратного вызова EvtWorkItem .

Дополнительные сведения о рабочих элементах см. в разделе Использование рабочих элементов платформы.

Примеры

Этот раздел содержит два примера. В первом примере показано, как добавить рабочие элементы в очередь для KMDF версии 1.7 и более поздних. Во втором примере показано, как добавить рабочие элементы в очередь для версий KMDF, предшествующих версии 1.7.

Пример 1. KMDF версии 1.7 и более поздних

В следующем примере кода вызывается локальная подпрограмма, которая возвращает указатель на контекстную память объекта рабочего элемента. В примере задается информация в контекстной памяти объекта, а затем вызывается WdfWorkItemEnqueue. Функция обратного вызова EvtWorkItem драйвера позже получит сведения из объекта work-item.

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. Версии KMDF до 1.7

В следующем примере кода вызывается локальная подпрограмма, которая возвращает указатель на контекстную память объекта рабочего элемента. В примере задаются сведения в контекстной памяти объекта, устанавливается переменная состояния "занят", а затем вызывается WdfWorkItemEnqueue. Функция обратного вызова EvtWorkItem драйвера позже получит сведения из объекта work-item.

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
Верхняя часть wdfworkitem.h (включая Wdf.h)
Библиотека 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