Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
312 views
in Technique[技术] by (71.8m points)

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

I have created a Visual Studio 2019 app, with OutputPanes, one is used for viewing Traces Logs from the WorkerThread.

In the WorkerThread, I fill a CStringList mStrDebugList if somewhat useful has happened, and inform the Main UI with PostMessage to read & show now.

//////////////////////////////////////////////////////////////////////////
//  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);
    }

This works, but if the App is minimized or not in the foreground, after hours the CStringList contains too many elements (> 20k) and the Main UI is unresponsive (~5Min) until all elements are read & removed in the 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);
    }
}

My question is, how can I check inside the WorkerThread if the UI is not active (dormant), to prevent filling the CStringList with too many elements?

question from:https://stackoverflow.com/questions/65830130/how-to-check-inside-the-worker-thread-if-the-main-ui-thread-is-sleeping-or-not-a

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I think your approach is wrong. What will you be doing if the UI (main) thread is "dormant"? Prevent the worker thread from working, ie suspend it? Will it no longer be collecting data? And what will happen when the UI is brought to the foreground again? The worker thread will have to collect ALL the data, which will still need to be added to the debug window, all at once, so the total response time will be yet longer.

If it's adding the data to the debug window (I guess a listbox-derived class) that takes so long, there is no real solution, they need to be added anyway. Only some optimizations:

  • Call m_wndOutputDebug.SetRedraw(FALSE); before adding the strings and m_wndOutputDebug.SetRedraw(TRUE); and m_wndOutputDebug.Invalidate(); when you are done, maybe the delay is caused by the UI attempting to draw the debug window immediately after each item is added.
  • Avoid those GetHead()/RemoveHead() calls for browsing the list (it's overhead, as it may rearrange/realloc the list), instead call RemoveAll() when you are done, there is no problem with this because you lock the operation.

A side note (not performance-related), why do you need to call AfxGetApp()? You are not doing anything with it (pApp) anyway. And you have the theApp singleton available (AfxGetApp() should just return the address of theApp, no?).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...