如果 Main UI 线程正在休眠或不活动,如何检查工作线程内部

How to check inside the Worker thread if the Main UI Thread is sleeping or not active

我创建了一个 Visual Studio 2019 应用程序,带有 OutputPanes,其中一个用于查看来自 WorkerThread 的跟踪日志。

在 WorkerThread 中,如果发生了一些有用的事情,我会填充一个 CStringList mStrDebugList,并通知 Main UI 和 PostMessage 现在阅读和显示。

//////////////////////////////////////////////////////////////////////////
//  TRACE Debug messsages for this App wide 
void TRACE_DEBUG(LPCTSTR pszstring)
{
    TRACE(pszstring);

    CTestApp* pApp = (CTestApp*)AfxGetApp();
    if (pApp)
    {
        TAutoLock lock(res);
        theApp.mStrDebugList.AddTail(pszstring);
    }

这可行,但如果应用程序最小化或不在前台,数小时后 CStringList 包含太多元素(> 20k)并且 Main UI 无响应(~5 分钟)直到 UI.

中的所有元素都被读取并删除
void COutputWnd::FillInfoWindow()
{
    TestApp* pApp = (CTestApp*)AfxGetApp();
    if (pApp)
    {
        TAutoLock lock(res);

        CString str;
        while (!theApp.mStrDebugList.IsEmpty ())
        {
            str.Format(_T("%5d %s"),nCounter, theApp.mStrDebugList.GetHead ());     
            m_wndOutputDebug.AddString (str);
            theApp.mStrDebugList.RemoveHead ();
        }

        // Scroll to the end of Listbox
        int nCount = m_wndOutputDebug.GetCount();
        m_wndOutputDebug.SetTopIndex(nCount-1);
    }
}

我的问题是,如果 UI 未激活(休眠),我如何检查 WorkerThread 内部,以防止用太多元素填充 CStringList

我认为你的做法是错误的。如果 UI(主)线程处于“休眠”状态,您将做什么?阻止工作线程工作,即挂起它?它会不再收集数据吗?当 UI 再次出现在前台时会发生什么?工作线程将不得不收集所有数据,这些数据仍然需要一次性添加到调试 window,因此总响应时间会更长。

如果将数据添加到调试 window(我猜是列表框派生的 class)需要很长时间,没有真正的解决方案,无论如何都需要添加它们。只有一些优化:

  • 在添加字符串之前调用 m_wndOutputDebug.SetRedraw(FALSE); 并在完成后调用 m_wndOutputDebug.SetRedraw(TRUE);m_wndOutputDebug.Invalidate();,延迟可能是由 UI 尝试绘制调试 window 添加每个项目后立即。
  • 避免那些 GetHead()/RemoveHead() 浏览列表的调用(这是开销,因为它可能 rearrange/realloc 列表),而不是在完成后调用 RemoveAll(),没有问题这是因为您锁定了操作。

旁注(与性能无关),为什么需要调用AfxGetApp()?无论如何,您没有对它做任何事情 (pApp)。并且您有可用的 theApp 单例(AfxGetApp() 应该只是 return theApp 的地址,不是吗?)。