MFC 应用程序在 CSingleLock Lock() 后挂起

Posted

技术标签:

【中文标题】MFC 应用程序在 CSingleLock Lock() 后挂起【英文标题】:MFC App hangs after CSingleLock Lock() 【发布时间】:2015-05-13 05:00:37 【问题描述】:
void CADAPBatchView::AddMsgToStatusWindow(const CString& strMsg)

    CString strTemp;
    CString strEngineStatusEntry;
    int nLinesToScrollPast = 0;
    int nTrimPos = 0;
    strEngineStatusEntry.Format(_T("%s %s\n"), CTime::GetCurrentTime().Format( _T( "%H:%M:%S" )), strMsg);

    CSingleLock singleLock( &m_csStatusMsg );
    singleLock.Lock();

    if (m_wndEngineStatusMsgs.GetLineCount() > 200)
    
        m_wndEngineStatusMsgs.SetReadOnly(FALSE);   //remove readonly so SetSel will work
        m_wndEngineStatusMsgs.SetSel(0, m_wndEngineStatusMsgs.LineIndex(100));
        m_wndEngineStatusMsgs.Clear();
        m_wndEngineStatusMsgs.SetReadOnly(TRUE);    //put back readonly
    

    int nBegin;
    nBegin = m_wndEngineStatusMsgs.GetTextLength();
    m_wndEngineStatusMsgs.SetSel(nBegin, nBegin);   // Select last character
    m_wndEngineStatusMsgs.ReplaceSel(strEngineStatusEntry);          // Append, move cursor to end of text
    //m_wndEngineStatusMsgs.SetSel(-1,0);             // Remove Black selection bars
    //nBegin = m_wndEngineStatusMsgs.GetTextLength(); // Get New Length
    //m_wndEngineStatusMsgs.SetSel(nBegin,nBegin);    // Cursor to End of new text

    nLinesToScrollPast = m_wndEngineStatusMsgs.GetLineCount() - 9 - m_wndEngineStatusMsgs.GetFirstVisibleLine();
    m_wndEngineStatusMsgs.LineScroll( nLinesToScrollPast );


    if (m_wndChkStatusMsgLog.GetCheck() == 1)
    
        WriteToLogFile(strEngineStatusEntry);
    

    return;

我附上了显示这两个线程的代码。在转储文件崩溃时,我看到主线程位于singlelock.Lock() 之后的行。第二个线程位于以nLinesToScrollPast 开头的行。我认为发生了死锁情况,但不知道如何。任何帮助表示赞赏,谢谢。

【问题讨论】:

不要附加图片链接,而是复制'n'粘贴重现问题所需的最少代码。 我怀疑所有SetSelReplaceSel 等都在包装SendMessage,当从工作线程调用时,它将永远等待被阻塞的主线程来处理它们。 首先,你没有附加任何代码,只是一个位图的链接(这在未来将无效,所以这个问题在未来没有意义)。其次,您没有为第二个线程显示任何代码。关于你的死锁:在调试器中启动程序并查看每个线程的调用堆栈,这样你就会明白为什么会出现死锁。 【参考方案1】:

问题是您试图使方法AddMsToStatusWindow 线程安全,以便从其他线程调用它。您的问题是只允许主应用程序线程与 GUI 交互,否则您最终会遇到消息泵问题(因为您确实锁定了SendMessage)。所以你的设计是错误的。您应该基于CCriticalSection 创建受保护的消息队列。所以线程会将消息放入队列,然后调用PostMessage 通知主线程数据/消息已放入队列。主线程将在消息处理程序中填充此队列中的数据。

【讨论】:

以上是关于MFC 应用程序在 CSingleLock Lock() 后挂起的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 CSingleLock 提供对该缓冲区的访问?

MFC规则动态库

推送通知参数本地化

为啥mfc中从InitInstance()中进入程序

如何将df.loc []应用于多行并应用转换?

mfc 图片列表显示