首页 > 解决方案 > 如果主 UI 线程处于睡眠状态或未处于活动状态,如何检查 Worker 线程内部

问题描述

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

在 WorkerThread 中,我填写了一个CStringList mStrDebugList如果发生了一些有用的信息,并通知主 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)并且主 UI 无响应(~5Min),直到在 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太多元素?

标签: winapimfc

解决方案


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

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

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

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


推荐阅读