Compartir a través de


Uso de colas de trabajo

En este tema se describe cómo usar colas de trabajo en Microsoft Media Foundation.

Uso de colas de trabajo

Una cola de trabajo es una manera eficaz de realizar operaciones asincrónicas en otro subproceso. Conceptualmente, se colocan elementos de trabajo en la cola y la cola tiene un subproceso que extrae cada elemento de la cola y lo envía. Los elementos de trabajo se implementan como devoluciones de llamada mediante la interfaz IMFAsyncCallback .

Media Foundation crea varias colas de trabajo estándar, denominadas colas de trabajo de plataforma. Las aplicaciones también pueden crear sus propias colas de trabajo, denominadas colas de trabajo privadas. Para obtener una lista de las colas de trabajo de la plataforma, consulte Identificadores de cola de trabajo. Para crear una cola de trabajo privada, llame a MFAllocateWorkQueue. Esta función devuelve un identificador para la nueva cola de trabajo. Para colocar un elemento en la cola, llame a MFPutWorkItem o MFPutWorkItemEx. En ambos casos, debe especificar una interfaz de devolución de llamada.

  • MFPutWorkItem toma un puntero a la interfaz IMFAsyncCallback , además de un objeto de estado opcional que implementa IUnknown. Estos son los mismos parámetros que se usan en métodos asincrónicos, como se describe en el tema Métodos de devolución de llamada asincrónica. Internamente, esta función crea un objeto de resultado asincrónico, que se pasa al método Invoke de la devolución de llamada.
  • MFPutWorkItemEx toma un puntero a la interfaz IMFAsyncResult . Esta interfaz representa un objeto de resultado asincrónico. Cree este objeto llamando a MFCreateAsyncResult y especificando la interfaz de devolución de llamada y, opcionalmente, un objeto de estado.

En ambos casos, el subproceso de cola de trabajo llama al método IMFAsyncCallback::Invoke . Use el método Invoke para realizar el elemento de trabajo.

Si más de un subproceso o componente comparte la misma cola de trabajo, puede llamar a MFLockWorkQueue para bloquear la cola de trabajo, lo que impide que la plataforma la libere. Para cada llamada a MFAllocateWorkQueue o MFLockWorkQueue, debe llamar a MFUnlockWorkQueue una vez para liberar la cola de trabajo. Por ejemplo, si crea una nueva cola de trabajo y, a continuación, la bloquea una vez, debe llamar a MFUnlockWorkQueue dos veces, una para la llamada a MFAllocateWorkQueue y una vez para la llamada a MFLockWorkQueue.

En el código siguiente se muestra cómo crear una nueva cola de trabajo, colocar un elemento de trabajo en la cola y liberar la cola de trabajo.

Consulte Work Queue and Threading Improvements (Mejoras de cola de trabajo y subprocesos) para obtener información adicional sobre las colas de trabajo en Windows 8.

DWORD idWorkQueue = 0;
HRESULT hr = S_OK;

// Create a new work queue.
hr = MFAllocateWorkQueue(&idWorkQueue);

// Put an item on the queue.
if (SUCCEEDED(hr))
{
    hr = MFPutWorkItem(idWorkQueue, pCallback, NULL);
}

// Wait for the callback to be invoked.
if (SUCCEEDED(hr))
{
    WaitForSingleObject(hEvent, INFINITE);
}

// Release the work queue.
if (SUCCEEDED(hr))
{
    hr = MFUnlockWorkQueue(idWorkQueue);
}

En este ejemplo se supone que pCallback es un puntero a la interfaz IMFAsyncCallback de la aplicación. También se supone que la devolución de llamada establece el identificador de eventos hEvent . El código espera a que este evento se establezca antes de llamar a MFUnlockWorkQueue.

Los subprocesos de cola de trabajo siempre se crean en el proceso del autor de la llamada. Dentro de cada cola de trabajo, las devoluciones de llamada se serializan. Si llama a MFPutWorkItem dos veces con la misma cola de trabajo, la segunda devolución de llamada no se invoca hasta que se devuelva la primera devolución de llamada.

Apagar colas de trabajo

Antes de llamar a MFShutdown, libere los recursos que usan los subprocesos de cola de trabajo. Para sincronizar este proceso, puede bloquear la plataforma Media Foundation, lo que impide que la función MFShutdown cierre los subprocesos de cola de trabajo. Si se llama a MFShutdown mientras la plataforma está bloqueada, MFShutdown espera unos cientos de milisegundos para que se desbloquee la plataforma. Si no se desbloquea en ese momento, MFShutdown cierra los subprocesos de cola de trabajo.

La implementación predeterminada de IMFAsyncResult bloquea automáticamente la plataforma Media Foundation cuando se crea el objeto de resultado. La liberación de la interfaz desbloquea la plataforma. Por lo tanto, casi nunca necesitará bloquear la plataforma directamente. Pero si escribe su propia implementación personalizada de IMFAsyncResult, debe bloquear y desbloquear manualmente la plataforma. Para bloquear la plataforma, llame a MFLockPlatform. Para desbloquear la plataforma, llame a MFUnlockPlatform. Para obtener un ejemplo, vea Objetos de resultados asincrónicos personalizados.

Después de llamar a MFShutdown, debe asegurarse de que la plataforma se desbloquea dentro del período de tiempo de espera de 5 segundos. Para ello, publique todos los punteros IMFAsyncResult y llame a MFUnlockPlatform si bloqueó la plataforma manualmente. Asegúrese de liberar los recursos que usan los subprocesos de cola de trabajo o que la aplicación podría perder memoria.

Normalmente, si la aplicación se apaga y libera todos los objetos de Media Foundation antes de llamar a MFShutdown, no tiene que preocuparse por el bloqueo. El mecanismo de bloqueo simplemente permite que los subprocesos de cola de trabajo salgan correctamente después de llamar a MFShutdown.

Usar elementos de trabajo programados

Puede programar una devolución de llamada para que se produzca después de un período de tiempo establecido llamando a MFScheduleWorkItem o MFScheduleWorkItemEx.

  • MFScheduleWorkItem toma un puntero a la devolución de llamada, un objeto de estado opcional y un intervalo de tiempo de espera.
  • MFScheduleWorkItemEx toma un puntero a un objeto de resultado asincrónico y un valor de tiempo de espera.

Especifique el tiempo de espera como un valor negativo en milisegundos. Por ejemplo, para programar una devolución de llamada que se invocará en 5 segundos, use el valor −5000. Ambas funciones devuelven un valor de MFWORKITEM_KEY , que puede usar para cancelar la devolución de llamada pasandolo a la función MFCancelWorkItem .

Los elementos de trabajo programados siempre usan la cola de trabajo de MFASYNC_CALLBACK_QUEUE_TIMER plataforma.

Uso de devoluciones de llamada periódicas

La función MFAddPeriodicCallback programa una devolución de llamada que se invocará periódicamente hasta que la cancele. El intervalo de devolución de llamada es fijo; las aplicaciones no pueden cambiarla. Para averiguar el intervalo exacto, llame a MFGetTimerPeriodicity. El intervalo está en el orden de 10 milisegundos, por lo que esta función está pensada para situaciones en las que se necesita un "tic" frecuente, como la implementación de un reloj de presentación. Si desea programar una operación para que se produzca con menos frecuencia, use un elemento de trabajo programado, como se ha descrito anteriormente.

A diferencia de las otras devoluciones de llamada descritas en este tema, la devolución de llamada periódica no usa la interfaz IMFAsyncCallback . En su lugar, usa un puntero de función. Para obtener más información, vea MFPERIODICCALLBACK Callback.

Para cancelar la devolución de llamada periódica, llame a MFRemovePeriodicCallback.

Las devoluciones de llamada periódicas usan la cola de trabajo de la plataforma MFASYNC_CALLBACK_QUEUE_TIMER.

Colas de trabajo

MFASYNCRESULT

Mejoras en la cola de trabajo y los subprocesos