在线程之间发送字符串数据(Win32)

时间:2009-06-09 04:46:18

标签: c++ multithreading winapi sendmessage

这是一个相当简单的问题,我基本上都在寻找一种“最佳实践”的方法来解决我想要做的事情。

我有一个Win32 GUI应用程序,它启动一个工作线程来执行一堆阻塞调用。我希望这个线程将字符串消息发送回GUI,以便它们显示给用户。

目前我在想使用SendMessage是一个很好的方法,使用WM_COPYDATA?这是正确的轨道吗?我最初有一个线程安全队列类,它将简单的通知消息发送回GUI线程,然后将该字符串从队列中弹出。然而,我很快退了一步,意识到我不需要队列;我可以直接发送字符串。

任何提示?谢谢!

编辑:为了完整起见,我正在使用C ++。

6 个答案:

答案 0 :(得分:2)

WM_COPYDATA可以正常工作,但我认为最好只定义自己的私有窗口消息。在完成后,在工作线程上分配字符串并在GUI线程上释放它。使用PostMessage而不是SendMessage,这样就不会不必要地阻止你的工作。

答案 1 :(得分:2)

正如其他几位人士指出的那样,自定义窗口消息可能是最佳方法。

要考虑的另一件事是使用的实际内存。通过在线程之间传递字符串,我猜你也在线程之间传递字符串的所有权。这可能会导致您应该注意的一些问题,包括

  • 内存泄漏:如果线程A发布消息并因此放弃所有权但在线程B处理消息之前窗口被销毁,会发生什么?
  • 内存管理器可以安全地支持你的字符串,并在不同的线程上释放内存。

第一个问题可能是影响您的应用程序的最大可能性。我认为这是重新考虑原始方法的一个很好的理由。只要队列本身得到妥善管理,您就可以消除内存泄漏,因为队列可以充当内存的临时所有者。

答案 2 :(得分:1)

WM_COPYDATA用于在进程之间发送,而不是在一个进程的线程之间发送。您当然可以将它用于线程间通信,但开销可能会更大,因为Windows可能需要做更多工作才能将数据复制到临时缓冲区并将其传递给接收应用程序。

如果您关心的是应用程序的简单性 - 坚持更容易实现的方式。如果关注的是性能 - 做个人资料并选择真正更快的变体。

答案 3 :(得分:1)

使用异步代理库,Visual Studio 2010使这些场景变得更加容易。您可以查看文档here中的演练,但这里有一些不那么伪代码:

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

如果我使用今天的工具集执行此操作,我将使用线程安全队列。

答案 4 :(得分:0)

在类似情况下,我总是将字符串放在资源文件中,并使用用户消息的一个参数来发送资源标识符。如果你需要发送动态信息,我会创建一个由UI线程分配的线程安全缓冲区,并将指向缓冲区的指针传递给工作线程。

答案 5 :(得分:0)

很大程度上取决于您希望信息流动的方式。

共享信息的最快方式可能是共享变量,其中包含某种形式的标记以防止竞争条件。如果有多个字符串,您可以拥有某种类型的队列。

但是,如果您没有数据同步经验,那么该模型很难正确。发送带有附加数据的自定义Windows消息可能会证明是一种更简单(减少错误)的模型。