首先,我不熟悉使用异步,所以下面的方法可能是完全错误的。我目前正在解码多个图像,并显示在一个对话框窗口。
只要我不试图在解码仍在运行时关闭对话框,这就可以正常工作。
如果关闭对话框,则会在return hh;
处收到调试Assert错误
在我的类头中,我有:
class CmytestDlg: public CDialog
{
protected:
// Generated message map functions
BOOL OnInitDialog() override;
std::future<HBITMAP> futurebmps[12];
};
在.cpp中:
BOOL CmytestDlg::OnInitDialog()
{
int totalJobs = 12;
// Queue up all the items,
for (int i = 0; i < totalJobs; i++)
{
futurebmps[i] = std::async(std::launch::async,
[this](const int i, const std::string& name) {
// This line is just here to simulate a long running image decode
std::this_thread::sleep_for(std::chrono::seconds(10));
HBITMAP hh = nullptr;
PostMessage(8888, i, 0); // Send a message to display the image
return hh; // <<< Debug Assertion Error Here (If I close dialog to soon)
}, i, std::to_string(0));
}
绘制图像的消息由OnRefreshAsyncView
处理:
LRESULT CmytestDlg::OnRefreshAsyncView(WPARAM wParam, LPARAM lParam)
{
// For the purpose of a minimal demo, even if this is empty It still casuses the issue.
return 0;
}
我相信这个问题是由调用PostMessage触发的,如果我注解掉这一行,我就不会再遇到崩溃。
我如何安全地处理对话框关闭的情况?这样我就可以防止这种崩溃。
2条答案
按热度按时间j1dl9f461#
我的通灵能力表明,您的ATL/MFC程序正在AssertPostMessage调用,因为窗口句柄在您关闭/销毁它之后变得无效。在PostMessage调用中间的某个地方有一个ASSERT,表明
m_hWnd
示例是非空的。因此,该Assert引起了对代码中一个真正错误的注意。PostMessage是Win32 API的 Package 器:PostMessage当您在另一个线程上调用 Package 器函数时,它可能会Assert
m_hWnd
(或类似的HWND成员)为非空。考虑编写额外的(线程安全的)代码(带有互斥锁),以防止在句柄上处理WM_CLOSE/WM_DESTROY的同时或之后调用PostMessage。
大概是这样的
其中OnClose是WM_CLOSE消息的处理程序,
isHwndValid
是类的bool成员,在创建窗口时被设置为true,_mutex
是std::mutex。3j86kqsm2#
要扩展selbie's answer:
如果希望线程提前停止,可以将该标志转换为std::atomic,并在计算期间定期检查它,例如: