CAMThread class

[The feature associated with this page, DirectShow, is a legacy feature. It has been superseded by MediaPlayer, IMFMediaEngine, and Audio/Video Capture in Media Foundation. Those features have been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use MediaPlayer, IMFMediaEngine and Audio/Video Capture in Media Foundation instead of DirectShow, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]

The CAMThread class is an abstract class for managing worker threads.

Protected Member Variables Description
m_hThread Handle to the thread.
Public Member Variables Description
m_AccessLock Critical section that locks the thread from being accessed by other threads.
m_WorkerLock Critical section that locks data shared among threads.
Public Methods Description
CAMThread Constructor method.
~ CAMThread Destructor method. Virtual.
InitialThreadProc Calls the ThreadProc method when the thread is created.
Create Creates the thread.
CallWorker Signals the thread with a request.
Close Waits for the thread to exit, then releases its resources.
ThreadExists Queries whether the thread exists.
GetRequest Waits for the next request.
CheckRequest Checks if there is a request, without blocking.
Reply Replies to a request.
GetRequestHandle Retrieves a handle to the event signaled by the CallWorker method.
GetRequestParam Retrieves the latest request.
CoInitializeHelper Calls CoInitializeEx at the start of the thread.
Pure Virtual Methods Description
ThreadProc Thread procedure.

Remarks

This class provides methods for creating a worker thread, passing requests to the thread, and waiting for the thread to exit. To use this class, do the following:

  • Derive a class from CAMThread and override the pure virtual method CAMThread::ThreadProc. This method is the thread procedure that gets called at the start of the thread.
  • In your application, create an instance of your derived class. Creating the object does not create the thread. To create the thread, call the CAMThread::Create method.
  • To send requests to the thread, call the CAMThread::CallWorker method. This method takes a DWORD parameter, whose meaning is defined by your class. The method blocks until the thread responds (see below).
  • In your thread procedure, respond to requests by calling either CAMThread::GetRequest or CAMThread::CheckRequest. The GetRequest method blocks until another thread calls CallWorker. The CheckRequest method is non-blocking, which enables the thread to check for new requests while working asynchronously.
  • When the thread receives a request, call CAMThread::Reply to unblock the calling thread. The Reply method takes a DWORD parameter, which is passed to the calling thread as the return value for CallWorker.

When you are done with the thread, call the CAMThread::Close method. This method waits for the thread to exit, and then closes the thread handle. Your ThreadProc message must be guaranteed to exit, either on its own or in response to a CallWorker request. The destructor method also calls Close.

The following example illustrates these steps:

class MyThread : public CAMThread
{
protected:
    DWORD ThreadProc(void);
};

DWORD MyThread::ThreadProc()
{
    BOOL bShutDown = FALSE;
    while (!bShutDown)
    {
        DWORD req = GetRequest();
        printf("Request: %d\n", req);
        bShutDown = (req == 0);
        Reply(bShutDown ? S_FALSE : S_OK);
    }
    printf("Quitting Thread\n");
    return 1;
}

void main()
{
    MyThread thread;
    DWORD reply;
    
    thread.Create();
    reply = thread.CallWorker(3);
    reply = thread.CallWorker(0); // Thread exits.
}

In your derived class, you can also define member functions that validate the parameters to CallWorker. The following example shows a typical way to do this:

enum Command {CMD_INIT, CMD_RUN, CMD_STOP, CMD_EXIT};

HRESULT Init(void)  { return CallWorker(CMD_INIT); }
HRESULT Run(void)   { return CallWorker(CMD_RUN); }
HRESULT Stop(void)  { return CallWorker(CMD_STOP); }
HRESULT Exit(void)  { return CallWorker(CMD_EXIT); }

The CAMThread class provides two critical sections as public member variables. Use CAMThread::m_AccessLock to lock the thread from being accessed by other threads. (For example, the Create and CallWorker methods hold this lock, to serialize operations on the thread.) Use CAMThread::m_WorkerLock to lock data that is shared among threads.

Requirements

Requirement Value
Header
Wxutil.h (include Streams.h)
Library
Strmbase.lib (retail builds);
Strmbasd.lib (debug builds)