Reputation: 67
I've written a simple console application using windows sockets to work as a proxy between a server and a client. I decided to make a graphical interface for watching all the in/outgoing packets real time (like a very simple wireshark).
The connection between the server and the client runs on a different thread than the message loop. When the server/client sends a packet, I would like that to be displayed (for example added to a simple text control) immediately.
But since I can not access the forms from other thread than the thread where the message loop is I dont know how to handle this.
I've found several solutions in: - Managed c++ - C++/CLI - C#, but not any without using .NET platform. (I really new to this GUI topic so I am not even sure you can use windows forms without .NET)
Maybe QT + C++ could handle this problem, but any other solution than that? If not is it possible to write a wrapper in C# / Java for the native C++ code?
There must be many applications written in C/C++ which using a GUI, what is the general way to do that?
Upvotes: 2
Views: 3386
Reputation: 186
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.
Upvotes: 2
Reputation: 122
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.
Upvotes: 0
Reputation: 1769
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
Upvotes: 2