我编写了一个简单的控制台应用程序,使用Windows套接字作为服务器和客户端之间的代理。我决定创建一个图形界面来实时观察所有输入/输出数据包(就像一个非常简单的wireshark)。
服务器和客户端之间的连接在与消息循环不同的线程上运行。当服务器/客户端发送数据包时,我希望立即显示(例如添加到简单的文本控件)。
但是因为我无法从其他线程访问表单而不是消息循环所在的线程,所以我不知道如何处理它。
我找到了几个解决方案: - 托管c ++ - C ++ / CLI - C#, 但没有使用.NET平台。 (我真的对这个GUI主题不熟悉,所以我甚至不确定你可以使用没有.NET的Windows表单)
也许QT + C ++可以解决这个问题,但除此之外的任何其他解决方案?如果没有,是否可以在C#/ Java中为本机C ++代码编写包装器?
必须有许多用C / C ++编写的使用GUI的应用程序,通常的方法是什么?
答案 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()不是解决方案在线程之间交换数据。