c ++多线程窗口GUI(访问表单)

时间:2012-01-04 23:55:34

标签: c++ multithreading winapi user-interface wrapper

我编写了一个简单的控制台应用程序,使用Windows套接字作为服务器和客户端之间的代理。我决定创建一个图形界面来实时观察所有输入/输出数据包(就像一个非常简单的wireshark)。

服务器和客户端之间的连接在与消息循环不同的线程上运行。当服务器/客户端发送数据包时,我希望立即显示(例如添加到简单的文本控件)。

但是因为我无法从其他线程访问表单而不是消息循环所在的线程,所以我不知道如何处理它。

我找到了几个解决方案: - 托管c ++ - C ++ / CLI - C#, 但没有使用.NET平台。 (我真的对这个GUI主题不熟悉,所以我甚至不确定你可以使用没有.NET的Windows表单)

也许QT + C ++可以解决这个问题,但除此之外的任何其他解决方案?如果没有,是否可以在C#/ Java中为本机C ++代码编写包装器?

必须有许多用C / C ++编写的使用GUI的应用程序,通常的方法是什么?

3 个答案:

答案 0 :(得分:2)

您完全无法访问其他线程中的窗口。处理此问题的正确方法是使用:: PostMessage Win32 API命令发布消息(或者,如果您在Win32周围使用包装器库,那么最终调用PostMessage的包装器中的任何函数)。以下是Microsoft关于消息队列的有用链接: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928(v=vs.85).aspx

答案 1 :(得分:1)

还有另一种免费开源,名为Nana C ++ Library(http://stdex.sourceforge.net),一个纯C ++ GUI库。 通过使用Nana库,可以轻松修复多线程问题。 GUI中的多线程有an article,它可以作为您的业余爱好项目的选择。

答案 2 :(得分:0)

快速而脏的Win32解决方案将涉及UI线程中的关键部分,文本缓冲区和计时器。

定义一些全局变量......

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线程计时器

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

从工作线程调用:

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

未经测试的代码。缓冲区大小和定时器频率需要调整。

使用PostMessage()(带有自定义消息)可以避免使用计时器轮询缓冲区,以通知UI新数据可用。

如果性能问题,生产者和消费者线程之间的数据交换也可以通过无锁FIFO队列非常有效地执行。

单独使用PostMessage()不是解决方案在线程之间交换数据。