c++ multithreaded windows GUI (accessing the forms)

淺唱寂寞╮ 提交于 2019-12-06 04:59:22

You are absolutely correct that you cannot access a window in a different thread. The proper way to handle this to post a message using the ::PostMessage Win32 API command (or, if you are using a wrapper library around Win32, whatever function in that wrapper that eventually calls PostMessage). Here's a useful link from Microsoft regarding message queues: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928(v=vs.85).aspx

There is an alternative one, free and open-source, called Nana C++ Library (http://stdex.sourceforge.net), a pure C++ GUI library. By using Nana library, the multithreading issue can be fixed easily. There is an article on the multithreading in GUI, it would be a choice for your hobby project.

A quick and dirty Win32 solution would involve a critical section, a text buffer, and a timer in the UI thread.

Define a few globals...

CRITICAL_SECTION bufferLock; // critical section (to be initialized somewhere)
char dataBuffer[65536]; // contains the data that will be sent to the form
int newdata = 0; // how much data we got (this variable must be atomic, int is ok)
char uiDataBuffer[65536]; // data available to the form
int overflow = 0; // just in case...

UI thread timer

void onTimer ()
{
     if (overflow)
     {
          // handle this
     }
     else
     if (newdata) // new data to display
     {
          // take the lock, copy the data and release the lock quickly
          EnterCriticalSection(&bufferLock);
          int dataread = newdata;
          memcpy(uiDataBuffer, dataBuffer, dataread);
          newdata = 0;
          LeaveCriticalSection(&bufferLock);

          // TODO: append the text in uiDataBuffer[] to your text control
     }
}

To be called from the worker thread:

void sendData (char* data, int size)
{
    EnterCriticalSection (&bufferLock);
    if(size+newdata > 65536)
        overflow = 1;
    else
    {
        memcpy(dataBuffer+newdata, data, size);
        newdata += size;
    }
    LeaveCriticalSection (&bufferLock);
}

Code untested. Buffer size and timer frequency are to be adjusted.

It is possible to avoid polling the buffer with the timer by using PostMessage() (with a custom message) to signal the UI that new data is available.

If performance is an issue, data exchange between a producer and a consumer thread can also be performed very efficiently with a lock-free FIFO queue.

PostMessage() alone is not a solution to exchange data between threads.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!