【问题标题】:Working with WINAPI with couple of threads通过几个线程使用 WINAPI
【发布时间】:2014-04-01 10:13:42
【问题描述】:

我已经在 WinAPI 上工作了一段时间,我注意到每当我尝试在不是主线程的线程中使用 WINAPI 函数(例如创建按钮/窗口/更新列表视图等)时,它只是不会出现。

因此,例如,如果我想向 ListView 添加项目,并且我调用一个函数,该函数接受一个字符串并将其添加到列表视图,如果我从主线程调用该函数,它会很好用,但是如果我从不同的线程调用它,它根本不起作用。

我能做什么?

【问题讨论】:

  • 你可以展示一些代码。并定义“根本不起作用”。

标签: c multithreading winapi


【解决方案1】:

与大多数(所有?)GUI 系统一样,您需要从拥有窗口的线程(通常是主线程)更新 GUI。您需要找到一种在两个线程之间进行通信的方法。在 Win32 中,我首选的方式是将user message 发送到 GUI 线程(通过PostMessage)并进行相应更新。您需要确保不会同时访问您在它们之间发送的数据,例如使用关键部分或其他方式保护全局数据。

一个简单的例子,半伪代码:

#define WM_MY_MESSAGE WM_USER+1

thread
{
    do some number crunching...
    // inform user
    EnterCriticalSection(&MessageCrit);
    strncpy(StatusMessageText, "Crunching away...", ARRAYSIZE(StatusMessageText));
    LeaveCriticalSection(&MessageCrit);
    PostMessage(hwndMain, WM_MY_MESSAGE, 0, 0); // You can utilize the params to your hearts content: structures, enums, etc...
}

guithread
{
switch (message)
{
case WM_INITDIALOG: // etc - whatever is in your normal message handler
    break;
case WM_MY_MESSAGE:
    ListView_InsertItem(...); // etc
    EnterCriticalSection(&MessageCrit); // Protect the global data
    ListView_SetItemText(item, StatusMessageText);
    LeaveCriticalSection(&MessageCrit);    
    break;
}
}

【讨论】:

  • 我不认为它必须是 main 线程。它必须是创建组件的线程,或者可能是包含消息泵的线程。
  • 其实,向其他线程上的windows发送消息可能的,是在windows上进行线程间通信的方式。将消息发布到线程,然后线程将相同的消息发布到窗口,这是多余的。但是,不可能,例如在一个线程上创建一个窗口,将另一个线程的窗口作为其父窗口。
  • 那么,如果我想通过不同的线程将一个项目添加到列表视图中,我应该在PostMessage函数中写什么?
  • 它应该可以正常工作-听起来您的问题出在其他地方。可以贴代码吗?
  • 当我在不是主线程的线程中使用ListView_InsertItemListView_SetItemText 时,它根本不起作用(并且它被调用),而在主线程中确实起作用..所以我不认为我有错误
【解决方案2】:

您应该使用PostMessage:

static LVITEM lvi = { ... };
PostMessage( myListView, LVM_INSERTITEM, 0, (LPARAM)&lvi );

或者,如果您需要返回值,请先为您的线程创建一个消息泵:

MSG msg;
PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE );
static LVITEM lvi = { ... };
ListView_InsertItem( myListView, &lvi );

如果您使用PostMessage,请确保在PostMessage 返回后也保持内存处于活动状态,因为消息由您的主线程异步处理。

【讨论】:

  • 我不明白你为什么要使用PostMessageLVM_INSERTITEM。你能解释一下为什么吗?
  • 在主窗口线程处理消息期间不阻塞发布线程。
  • 但是这样做会给LVITEM结构带来巨大的生命周期管理问题。
  • 这取决于底层架构。例如,LVITEM 结构可以是聚合结构的一部分,该结构表示工作项,由工作线程拥有,始终对应于列表视图中的一行。
  • 比较常见的是它是本地的。保留全局 LVITEM 对象将是糟糕设计的标志。
猜你喜欢
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 2017-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
相关资源
最近更新 更多