0

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

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

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

有小费吗?谢谢!

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

4

6 回答 6

2

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

于 2009-06-09T04:56:01.657 回答
2

正如其他几个人指出的那样,自定义窗口消息可能是这里最好的方法。

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

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

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

于 2009-06-09T05:03:32.240 回答
1

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

如果您关心的是应用程序的简单性 - 坚持使用更容易实现的方式。如果关注的是性能 - 进行配置并选择真正更快的变体。

于 2009-06-09T04:54:37.633 回答
1

Visual Studio 2010 使用异步代理库大大简化了这类场景。您可以在此处查看文档中的演练,但这里有一些不那么伪代码:

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

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

于 2009-06-10T05:51:36.647 回答
0

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

于 2009-06-09T04:56:25.027 回答
0

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

共享信息的最快方式可能是与某种形式的哨兵共享变量以防止竞争条件。如果有多个字符串,您可能会有某种队列。

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

于 2009-06-09T09:57:20.237 回答