2012-01-04 53 views
2

我写了一个简单的控制台应用程序,使用Windows套接字作为服务器和客户端之间的代理工作。我决定创建一个图形界面来实时观看所有进/出包(就像一个非常简单的wireshark)。C++多线程窗口GUI(访问表单)

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

但因为我不能从其他线程访问的形式比线程其中消息循环是我不知道如何来处理这个问题。

我已经发现了几个解决方案: - 托管C++ - C++/CLI - C#, 但并非没有任何使用.NET平台。 (我真的很新的这个GUI话题,所以我甚至不能确定,你可以使用windows形式,而不.NET)

也许QT + C++可以处理这个问题,但没有其他解决办法比?如果不是,可以在C#/ Java中为本机C++代码编写包装器吗?

用C/C++,其使用GUI

一定有很多的应用,什么是做到这一点的一般方法是什么?

+1

将次要线程的自定义消息发布到对话框。 – ildjarn 2012-01-04 23:57:14

回答

2

你是绝对正确的,你不能访问另一个线程中的窗口。使用:: PostMessage Win32 API命令处理此问题的正确方法(或者,如果您使用的是Win32的包装器库,则该包装器中最终调用PostMessage的任何函数)。以下是来自Microsoft有关消息队列的有用链接: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928(v=vs.85).aspx

+0

PostMessage +1() – 2012-01-05 00:24:06

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()不是线程间交换数据的解决方案

+0

这两个答案都非常有帮助,感谢他们。有没有优雅的方式来使用自定义消息? (我的意思是如果我使用自定义消息 - 让它成为PACKET_ARRIVED - 它必须有一个int类型。如何确保它的值不与其他常量冲突?我应该只使用一个足够大的数字吗?以避免冲突? – user1131015 2012-01-05 01:59:59

+0

尝试WM_USER +东西 – rkosegi 2012-01-05 16:21:05

+0

使用RegisterWindowMessage()获取唯一的“自定义”消息。 – al01 2012-01-05 17:06:28

1

有一个可供选择的一个,自由和开源,称为奈C++库(http://stdex.sourceforge.net),纯C++ GUI库。 通过使用Nana库,可以很容易地解决多线程问题。在GUI中有多线程的an article,这将是您的爱好项目的选择。