다음을 통해 공유


작업 큐 사용

이 항목에서는 Microsoft Media Foundation에서 작업 큐를 사용하는 방법을 설명합니다.

작업 큐 사용

작업 큐는 다른 스레드에서 비동기 작업을 수행하는 효율적인 방법입니다. 개념적으로 작업 항목을 큐에 배치하고 큐에는 큐에서 각 항목을 끌어와 디스패치하는 스레드가 있습니다. 작업 항목은 IMFAsyncCallback 인터페이스를 사용하여 콜백으로 구현됩니다.

Media Foundation은 플랫폼 작업 큐라는 여러 표준 작업 큐를 만듭니다. 애플리케이션은 프라이빗 작업 큐라는 자체 작업 큐를 만들 수도 있습니다. 플랫폼 작업 큐 목록은 작업 큐 식별자를 참조하세요. 프라이빗 작업 큐를 만들려면 MFAllocateWorkQueue를 호출합니다. 이 함수는 새 작업 큐에 대한 식별자를 반환합니다. 큐에 항목을 배치하려면 MFPutWorkItem 또는 MFPutWorkItemEx를 호출합니다. 두 경우 모두 콜백 인터페이스를 지정해야 합니다.

  • MFPutWorkItemIMFAsyncCallback 인터페이스에 대한 포인터와 IUnknown을 구현하는 선택적 상태 개체를 사용합니다. 비동기 콜백 메서드 항목에 설명된 대로 비동기 메서드에 사용되는 것과 동일한 매개 변수입니다. 내부적으로 이 함수는 콜백의 Invoke 메서드에 전달되는 비동기 결과 개체를 만듭니다.
  • MFPutWorkItemExIMFAsyncResult 인터페이스에 대한 포인터를 사용합니다. 이 인터페이스는 비동기 결과 개체를 나타냅니다. MFCreateAsyncResult를 호출하고 콜백 인터페이스 및 필요에 따라 상태 개체를 지정하여 이 개체를 만듭니다.

두 경우 모두 작업 큐 스레드는 IMFAsyncCallback::Invoke 메서드를 호출합니다. Invoke 메서드를 사용하여 작업 항목을 수행합니다.

둘 이상의 스레드 또는 구성 요소가 동일한 작업 큐를 공유하는 경우 MFLockWorkQueue 를 호출하여 작업 큐를 잠그면 플랫폼이 해제되지 않습니다. MFAllocateWorkQueue 또는 MFLockWorkQueue를 호출할 때마다 MFUnlockWorkQueue를 한 번 호출하여 작업 큐를 해제해야 합니다. 예를 들어 새 작업 큐를 만든 다음 한 번 잠그는 경우 MFAllocateWorkQueue 호출에 대해 한 번, MFLockWorkQueue 호출에 대해 한 번, MFUnlockWorkQueue 호출에 대해 MFUnlockWorkQueue를 두 번 호출해야 합니다.

다음 코드에서는 새 작업 큐를 만들고, 작업 항목을 큐에 배치하고, 작업 큐를 해제하는 방법을 보여 있습니다.

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);
}

이 예제에서는 pCallback 이 애플리케이션의 IMFAsyncCallback 인터페이스에 대한 포인터라고 가정합니다. 또한 콜백이 hEvent 이벤트 핸들을 설정한다고 가정합니다. 코드는 MFUnlockWorkQueue를 호출하기 전에 이 이벤트가 설정되기를 기다립니다.

작업 큐 스레드는 항상 호출자의 프로세스에서 만들어집니다. 각 작업 큐 내에서 콜백이 직렬화됩니다. 동일한 작업 큐에서 MFPutWorkItem 을 두 번 호출하는 경우 첫 번째 콜백이 반환될 때까지 두 번째 콜백이 호출되지 않습니다.

작업 큐 종료

MFShutdown을 호출하기 전에 작업 큐 스레드에서 사용되는 모든 리소스를 해제합니다. 이 프로세스를 동기화하려면 MFShutdown 함수가 작업 큐 스레드를 닫지 못하도록 하는 Media Foundation 플랫폼을 잠글 수 있습니다. 플랫폼이 잠겨 있는 동안 MFShutdown 이 호출되면 MFShutdown 은 플랫폼 잠금이 해제될 때까지 수백 밀리초 정도 기다립니다. 해당 시간 내에 잠금 해제되지 않은 경우 MFShutdown 은 작업 큐 스레드를 닫습니다.

IMFAsyncResult의 기본 구현은 결과 개체가 만들어질 때 Media Foundation 플랫폼을 자동으로 잠가야 합니다. 인터페이스를 해제하면 플랫폼의 잠금이 해제됩니다. 따라서 플랫폼을 직접 잠글 필요가 거의 없습니다. 그러나 IMFAsyncResult의 사용자 지정 구현을 작성하는 경우 플랫폼을 수동으로 잠그고 잠금을 해제해야 합니다. 플랫폼을 잠그려면 MFLockPlatform을 호출합니다. 플랫폼의 잠금을 해제하려면 MFUnlockPlatform을 호출합니다. 예제는 사용자 지정 비동기 결과 개체를 참조하세요.

MFShutdown을 호출한 후에는 플랫폼이 5초 제한 시간 내에 잠금 해제되었는지 확인해야 합니다. 모든 IMFAsyncResult 포인터를 해제하고 플랫폼을 수동으로 잠근 경우 MFUnlockPlatform 을 호출하여 이 작업을 수행합니다. 작업 큐 스레드에서 사용 중인 리소스를 해제하거나 애플리케이션이 메모리를 누수할 수 있는지 확인합니다.

일반적으로 애플리케이션이 MFShutdown을 호출하기 전에 모든 Media Foundation 개체를 종료하고 해제하는 경우 잠금에 대해 걱정할 필요가 없습니다. 잠금 메커니즘을 사용하면 MFShutdown을 호출한 후 작업 큐 스레드가 정상적으로 종료됩니다.

예약된 작업 항목 사용

MFScheduleWorkItem 또는 MFScheduleWorkItemEx를 호출하여 설정된 기간 후에 콜백이 발생하도록 예약할 수 있습니다.

  • MFScheduleWorkItem 은 콜백, 선택적 상태 개체 및 시간 제한 간격에 대한 포인터를 사용합니다.
  • MFScheduleWorkItemEx 는 비동기 결과 개체 및 시간 제한 값에 대한 포인터를 사용합니다.

시간 초과를 음수 값(밀리초)으로 지정합니다. 예를 들어 콜백이 5초 안에 호출되도록 예약하려면 값 -5000을 사용합니다. 두 함수 모두 MFCancelWorkItem 함수에 전달하여 콜백을 취소하는 데 사용할 수 있는 MFWORKITEM_KEY 값을 반환합니다.

예약된 작업 항목은 항상 MFASYNC_CALLBACK_QUEUE_TIMER 플랫폼 작업 큐를 사용합니다.

주기적 콜백 사용

MFAddPeriodicCallback 함수는 취소할 때까지 콜백이 주기적으로 호출되도록 예약합니다. 콜백 간격이 수정되었습니다. 애플리케이션은 변경할 수 없습니다. 정확한 간격을 확인하려면 MFGetTimerPeriodicity를 호출합니다. 간격은 10밀리초 단위이므로 이 함수는 프레젠테이션 클록 구현과 같이 빈번한 "틱"이 필요한 상황에 적합합니다. 작업을 덜 자주 수행하도록 예약하려면 앞에서 설명한 대로 예약된 작업 항목을 사용합니다.

이 항목에 설명된 다른 콜백과 달리 주기적인 콜백은 IMFAsyncCallback 인터페이스를 사용하지 않습니다. 대신 함수 포인터를 사용합니다. 자세한 내용은 MFPERIODICCALLBACK 콜백을 참조하세요.

주기적인 콜백을 취소하려면 MFRemovePeriodicCallback을 호출합니다.

주기적인 콜백은 MFASYNC_CALLBACK_QUEUE_TIMER 플랫폼 작업 큐를 사용합니다.

작업 큐

MFASYNCRESULT

작업 큐 및 스레딩 개선 사항