Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

MFC UI Threads

0.00/5 (No votes)
17 Aug 2004 6  
A simple UI thread example.

Image of demo application

Introduction

This article describes a quick UI thread implementation. Running the demo project will create two modal dialog windows. They will initially appear right on top of each other. Move the top window off to the side so you can see both windows.

Each dialog is run in a different thread, and each dialog will maintain a separate message loop. This behavior can be seen by clicking on the Lock button for each thread. After clicking on "Lock", the thread will attempt to acquire access to the named lock "ThreadLockExample". If the thread gets access to the lock, a "Got Lock" message will be displayed. If the thread is unable to get access to the lock, then a "Waiting" message will be displayed. The locking behavior seen in these two dialogs could not occur without using UI threads. Why? There are 2 reasons:

  1. If two dialogs are running within 1 thread, then waiting for the lock would halt both threads.
  2. You could not create a separate dialog in a worker thread. Worker threads do not have a message loop.

Source Code

  • Lock.h/cpp

    Manages a single lock, and abstracts away implementation details from user.

  • UIThread.h/cpp

    Implementation of a UI thread.

  • ThreadExDlg.h/cpp

    Thread dialog.

  • ThreadEx.h/cpp

    Thread example main app.

Code Notes

Creating a thread

To create a user interface thread, create an instance of a class derived from CWinThread. Then, call the method CreateThread. See UIThread.h/cpp and ThreadEx.cpp for more information.

class UIThread : public CWinThread
    ...
};
...
BOOL CThreadexApp::InitInstance()
{
    ...
    // Create a thread to generate a maintain a instance of CThreadexDlg.

    thread.CreateThread();
    ...
}

Create a mutex (lock)

To create a lock, just call CreateMutex(...). See Lock.h/cpp.

CDMLock::CDMLock(const CString & name)
{
    mutex = CreateMutex(NULL, 0, name);
}

Acquire lock (down)

Call WaitForSingleObject(...). You can optionally pass a timeout value. When you have waited longer than the specified time, the function WaitForSingleObject will return WAIT_TIMEOUT. If the lock is acquired successfully, it will return WAIT_OBJECT_0.

// Get lock. If timeout expires than return fail.

bool CDMLock::Lock(DWORD timeout)
{
    if (mutex) {
        if (WaitForSingleObject(mutex, timeout) == WAIT_OBJECT_0) 
            return true;
    }
    return false;
}

Release Lock (up)

// Release lock.

bool CDMLock::Unlock()
{
    if (mutex) {
        if (ReleaseMutex(mutex))
            return true;
    }
    return false;
}

CDMLock (Reusable)

Most of the code included in the download for this article is demo code. But the class CDMLock (lock.h/cpp) is kind of a nice class to have around. While working with locks really is not that difficult, it is always nice to have the details abstracted away. CDMLock is pretty simple to use. Just pass a string into the constructor to create a Named Lock. Then call Lock to acquire access to the lock. Call Unlock to release the lock. For an example of the usage of CDMLock, look at ThreadExDlg.cpp.

The CDMLock class can also be used for two processes running on the same computer, not just two threads in the same process.

class CDMLock  
{
public:
    CDMLock(const CString & name);
    virtual ~CDMLock();
    bool Unlock();
    bool Lock(DWORD timeout = INFINITE);
   
private:
    HANDLE mutex;
};

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here