MFC数据通过PostMessage转发到主线程

11 浏览
0 Comments

MFC数据通过PostMessage转发到主线程

我需要重构一个C++/MFC应用程序。该应用程序以前在主线程上处理大部分数据,因此会阻塞输入,现在我想改变它,使所有GUI更新都通过PostMessage完成。

不幸的是,我似乎找不到一个好的方法来实现这个目标的来源。

现在我考虑创建一个由关键部分保护的优先级队列,一个工作线程(while(true))来处理这个队列,并通过PostMessage机制将数据指针发送到主线程。

我对这种方法感到担忧的是,PostMessage不能保证一定到达主线程,所以,如果我理解正确,存在内存泄漏的可能性。

第二个问题是,另一个应用程序可以向我的应用程序发送自定义消息,我的应用程序可能会尝试将WPARAM或LPARAM解引用为指针,从而导致AV(访问冲突)。

有人知道这种任务的最佳实践是什么吗?

这些数据可以是Web控件的HTML内容,也可以是列表框、下拉框等的其他内容。

0
0 Comments

MFC数据通过PostMessage转发到主线程的原因是为了解决多线程中数据传递的问题。在多线程应用程序中,当工作线程需要将数据传递给主线程时,可以使用PostMessage函数来通知主线程从队列中获取数据。这样可以避免直接在多个线程之间共享数据,从而减少了数据竞争和线程安全性问题。

为了实现这一功能,可以使用两个队列,一个用于将工作请求发送到工作线程,另一个用于将结果返回给主线程。工作线程在完成任务后,将结果放入结果队列中。主线程可以通过调用PostMessage函数来唤醒,并告诉它检查结果队列。这样主线程就可以在需要时获取结果,并进行进一步的处理。

在使用PostMessage函数时,不需要在消息中传递任何参数。因为工作线程已经将结果放入队列中,主线程只需要通过PostMessage函数告知它检查队列即可。这样可以简化消息传递的过程,减少了代码的复杂性。

下面是一个使用PostMessage函数实现MFC数据转发的示例:

// 在主线程中处理消息
LRESULT CMyWnd::OnDataArrival(WPARAM wParam, LPARAM lParam)
{
    // 检查结果队列并处理数据
    while (!m_resultQueue.empty())
    {
        // 从结果队列中获取数据
        Data data = m_resultQueue.front();
        m_resultQueue.pop();
        // 处理数据
        ProcessData(data);
    }
    return 0;
}
// 在工作线程中发送数据到主线程
void CMyWorkerThread::SendDataToMainThread(Data data)
{
    // 将数据放入结果队列
    m_resultQueue.push(data);
    // 唤醒主线程并告知检查队列
    ::PostMessage(m_hWnd, WM_DATA_ARRIVAL, 0, 0);
}

通过上述示例,可以看到主线程通过处理WM_DATA_ARRIVAL消息从结果队列中获取数据并进行处理。工作线程在完成任务后,将数据放入结果队列,并通过PostMessage函数通知主线程检查队列。这样就实现了MFC数据的转发,解决了多线程中数据传递的问题。

总结起来,MFC数据通过PostMessage函数转发到主线程的原因是为了解决多线程中数据传递的问题。通过使用两个队列和PostMessage函数,可以简化消息传递的过程,降低代码的复杂性。这种方式可以有效地避免数据竞争和线程安全性问题,提高了多线程应用程序的性能和稳定性。

0
0 Comments

MFC数据通过PostMessage转发到主线程的问题出现的原因是,PostMessage函数可能会失败,返回错误代码,这通常是由于窗口消息队列已满引起的。默认情况下,Windows消息队列的大小限制为4000条消息,可以通过注册表设置将其增加到最大10000条消息。如果消息队列已满,调用PostMessage函数会失败,并返回错误代码。如果应用程序运行在消息队列达到上限的情况下,应用程序会出现问题,无法正常运行,屏幕无法更新,处理过程会变得迟钝,可能会发生各种错误。因此,需要检查PostMessage函数的返回值,并确保消息队列不会达到上限。

解决这个问题的方法是,避免使用队列在线程之间传递数据。可以通过在堆上创建一个包含数据的数据结构,并告诉另一个线程“我有数据给你,这是数据”。接收线程然后接管该数据指针,并负责删除它。这样做的好处是避免了硬锁的使用。

如果是从工作线程发送数据到主线程,可以使用PostMessage函数。在工作线程中创建一个数据对象,并使用PostMessage函数将其传递给主线程。主线程接收到消息后,处理数据并删除数据对象。

如果是从主线程发送数据到工作线程,可以使用QueueUserAPC函数或PostThreadMessage函数。使用QueueUserAPC函数时,需要确保工作线程处于可接收的等待状态。使用PostThreadMessage函数时,直接将数据发送给工作线程。

如果担心外部应用程序的自定义消息会干扰自己的消息,可以使用RegisterWindowsMessage函数获取一个唯一的消息ID。

另外,当应用程序关闭时,Windows会回收内存,不需要手动释放。需要注意的是,其他资源需要根据具体情况进行处理,避免资源泄漏。

总之,通过在堆上创建数据结构并使用PostMessage函数将数据传递给另一个线程,可以避免使用队列在线程之间传递数据时出现的问题。需要注意PostMessage函数可能会失败的情况,并及时处理错误。

0
0 Comments

MFC数据通过PostMessage转发到主线程的问题是由于在后台线程和UI(主)线程之间传递数据时出现的。为了解决这个问题,我创建了一个单例队列来保存需要从后台线程流向UI线程的数据(或操作)。该队列由临界区保护。后台线程会将其数据放入队列并发送一条消息。这条消息不包含任何数据,它只是一个简单的唤醒信号,告诉主线程:“嘿,主线程,看看队列,有工作要做”。

这样,你就不会有内存泄漏或其他资源泄漏的风险;队列可以安全地销毁,其中包含的所有数据也会被销毁。

但是,这种方法有一个问题。它将两个线程串行化,从而抵消了使用多个核心所带来的所有好处,并增加了复杂性。

实际上,你并不需要将线程串行化。关键点是只在从队列中提取命令实例时持有队列锁,并在释放锁后,使后台线程可以继续向队列中添加数据而无需等待。后台线程只在需要将新成员放入队列时才持有锁。

但是,这实际上就是串行化的定义。两个线程不能同时访问队列。

John:队列访问是快速且原子的。你可以在几个CPU周期内交换指针。关键任务是将在不同线程中发生的数据处理分离开来。在我们的情况下,没有线程等待另一个线程完成数据处理。再次强调,锁只是为了保护队列的数据结构的完整性。

0