Winapi 如何在工作线程内部检查主UI线程是否处于睡眠状态或未处于活动状态

Winapi 如何在工作线程内部检查主UI线程是否处于睡眠状态或未处于活动状态,winapi,mfc,Winapi,Mfc,我创建了一个VisualStudio2019应用程序,带有OutputPanes,其中一个用于从WorkerThread查看跟踪日志 在WorkerThread中,如果发生了一些有用的事情,我将填充一个CStringList mStrDebugList,并用PostMessage通知主UI立即读取和显示 ////////////////////////////////////////////////////////////////////////// //此应用程序范围内的跟踪调试消息 无效跟踪

我创建了一个VisualStudio2019应用程序,带有OutputPanes,其中一个用于从WorkerThread查看跟踪日志

在WorkerThread中,如果发生了一些有用的事情,我将填充一个
CStringList mStrDebugList
,并用
PostMessage
通知主UI立即读取和显示

//////////////////////////////////////////////////////////////////////////
//此应用程序范围内的跟踪调试消息
无效跟踪调试(LPCTSTR pszstring)
{
跟踪(pszstring);
CTestApp*pApp=(CTestApp*)AfxGetApp();
if(pApp)
{
重锁锁;
app.mStrDebugList.AddTail(pszstring);
}
这是可行的,但如果应用程序被最小化或不在前台,则在数小时后,
CStringList
包含太多元素(>20k),并且主UI没有响应(~5Min),直到在UI中读取并删除所有元素

void COutputWnd::FillInfoWindow()
{
TestApp*pApp=(CTestApp*)AfxGetApp();
if(pApp)
{
重锁锁;
CString-str;
而(!theApp.mStrDebugList.IsEmpty())
{
str.Format(_T(“%5d%s”),n计数器,theApp.mStrDebugList.GetHead();
m_wndOutputDebug.AddString(str);
theApp.mStrDebugList.RemoveHead();
}
//滚动到列表框的末尾
int nCount=m_wndOutputDebug.GetCount();
m_wndOutputDebug.SetTopIndex(nCount-1);
}
}

我的问题是,如果UI未处于活动(休眠)状态,如何检查WorkerThread内部,以防止在
CStringList
中填充过多的元素?

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

如果将数据添加到调试窗口(我猜是listbox派生的类)需要很长时间,那么没有真正的解决方案,仍然需要添加数据。只有一些优化:

  • 在添加字符串之前调用
    m_-wndOutputDebug.SetRedraw(FALSE);
    ,然后
    m_-wndOutputDebug.SetRedraw(TRUE);
    m_-wndoutdebug.Invalidate();
    完成后,延迟可能是由于用户界面试图在添加每个项目后立即绘制调试窗口造成的
  • 避免那些用于浏览列表的
    GetHead()/RemoveHead()
    调用(这是开销,因为它可能会重新排列/realloc列表),而是在完成后调用
    RemoveAll()

一个旁注(与性能无关),为什么需要调用
AfxGetApp()
?无论如何,你没有用它做任何事情(
pApp
)。而且你有
theApp
单件可用(
AfxGetApp()
应该只返回
theApp
,没有?)。

你提到了“睡眠”这个词。您是否真的从UI线程调用了
sleep()
?实际的UI线程应保持对消息的响应,并且不应将其置于睡眠状态。如果这是您所说的“睡眠”,则“编辑重言式”应该是可以的,只要您不锁定除单个日志项之外的资源。消息循环和UI不会因为窗口被隐藏/最小化而停止工作。您说您正在使用
PostMessage()
,但在显示的代码中没有此类调用。真正的问题是,无论您使用什么来触发
FillInfoWindow())
无法正常工作。请修复此问题。感谢状态UI,如果窗口被隐藏/最小化,请不要停止工作。这是真的,我不再确定。我已推迟发布真实消息,以更新OnPaint中的输出消息
AfxGetMainWnd()->sendMessageToDescendats(WM_命令,AFX_id_IDLEMESSAGE);//更新输出Wnd
。这就解释了这个问题。是的,我还试图以非常错误的方式解决OutputWindow中的闪烁问题,方法是减慢WorkerThread。感谢您提供的优化提示。特别是我不知道AfxGetApp占用了很多CPU周期。我在我的机器上测量到了~300us vs~40us。