views:

696

answers:

6

Hi all,

This is a fairly straightforward question, I'm basically looking for a 'best practice' approach to what I'm trying to do.

I have a Win32 GUI application which starts up a worker thread to do a bunch of blocking calls. I want this thread to send string messages back to the GUI so they can be displayed to the user.

Currently I'm thinking the use of SendMessage would be a good approach, using WM_COPYDATA? Is this on the right track? I did originally have a thread safe queue class which sent simple notification messages back to the GUI thread, which then popped the string off the queue. However I soon took a step back and realised I didn't need the queue; I could just send the string directly.

Any tips? Thanks!

Edit: And for completeness, I'm using C++.

+1  A: 

WM_COPYDATA is for sending between processes, not between threads of one process. You certainly can use it for interthread communication but the overhead could be bigger because Windows would presumably need to do some more work to copy the data to a temporary buffer and pass it to the receiving application.

If your concern is simplicity of the application - stick to the way which is easier to implement. If the concern is performance - do profile and choose the variant which is really faster.

sharptooth
+2  A: 

WM_COPYDATA would work fine, but I think it's better to simply define your own private window message. Allocate the string on the worker thread and free it on the GUI thread when you're done. Use PostMessage instead of SendMessage so that you don't block your worker unnecessarily.

Peter Ruderman
A: 

In similar situations I have always put the strings in a resource file, and used one of the params of a user message to send the resource identifier. If you need to send dynamic information, I would create a threadsafe buffer, allocated by the UI thread, and pass a pointer to the buffer to the worker thread.

Robert
+2  A: 

As several others have pointed out a custom window message may be the best approach here.

Another thing to consider is the actual memory being used. By passing the string between threads, I'm guessing that you are also passing ownership of the string between threads. This can cause a few issues you should be aware of including

  • Memory leaks: What happens if Thread A posts the messages and hence gives away ownership but the window is destroyed before Thread B processes the message
  • Can the memory manager backing your string safely allocate and free memory on different threads.

The first issue is probably the one that has the biggest chance of impacting your application. I think this is a good reason to re-consider your original approach. As long as the queue itself is properly managed you can eliminate the memory leak as the queue can serve as a temporary owner of the memory.

JaredPar
A: 

A lot depends on the way you want the information to flow.

The fastest way to share the information might be a shared variable with some form of sentinel to prevent race conditions. If there are multiple strings, you could have a queue of some sort.

However that model can be hard to get correct if you don't have experience in data synchronisation. Sending a custom Windows message with the data attached might prove a simpler (less buggy) model.

Michael J
+1  A: 

Visual Studio 2010 is making these kinds of scenarios significantly easier with the Asynchronous Agents Library. You can take a look at the walkthroughs in documentation here, but here's some not so pseudo-code:

//somewhere stateful, e.g. main
unbounded_buffer<stringtype> buff;

//thread 1
{
  //send a message asynchronously to the buffer
  asend(&buff,stringtype("hello world");
}

//thread 2
{
  //get the message out of the buffer
  //if this is a UI thread, receive is blocking so use try_receive which isn't
  stringtype message = receive(&buff)
}

If I was doing this with today's toolset, I would use a threadsafe queue.

Rick