Лучший способ показать прогресс фонового потока в ATL? - PullRequest
0 голосов
/ 28 ноября 2011

При использовании ATL, как лучше всего отобразить ход фонового потока (например, при поиске файла), не блокируя пользовательский интерфейс?

Я все еще хочу иметь возможность обрабатывать сообщения, разрешить использование кнопки «Отмена» и, возможно, позволить пользователю продолжить работу с программой во время поиска.

1 Ответ

1 голос
/ 29 ноября 2011

Здесь нет конкретных ATL.Один из способов сделать это - обновить сведения о ходе выполнения в переменной-члене и опубликовать сообщение в окне GUI, а затем обработать сообщение, извлекая данные из переменной-члена и обновляя GUI, например, обновляя статическую и / или индикатор выполнения.

Псевдокод рабочего потока:

m_DataCriticalSection.Lock();
m_nProgress = (INT) (nCurrent * 100 / nTotal);
m_DataCriticalSection.Unlock();
PostMessage(WM_MYUPDATEPROGRESS);

Окно:

OnMyUpdateProgress()
{
  m_DataCriticalSection.Lock();
  INT nProgress = m_nProgress;
  m_DataCriticalSection.Unlock();
  m_ProgressBar.SetPos(nProgress);
}

UPD.В фоновом потоке вызывается фрагмент реального кода , AddText,

    VOID AddText(const CString& sText)
    {
            _A(sText.Find(_T('\n')) < 0);
            BOOL bIsTextEmpty;
            {
                    CRoCriticalSectionLock TextLock(m_TextCriticalSection);
                    bIsTextEmpty = m_sText.IsEmpty();
                    m_sText.Append(sText);
                    m_sText.Append(_T("\r\n"));
            }
            if(bIsTextEmpty)
                    PostPrivateMessage(WM_UPDATETEXT);
    }

и обработчик кода :

BEGIN_MSG_MAP_EX(CMainDialog)
        // ...
        MESSAGE_HANDLER_EX(WM_UPDATETEXT, OnUpdateText)

    LRESULT OnUpdateText(UINT, WPARAM, LPARAM)
    {
            CString sText;
            {
                    CRoCriticalSectionLock TextLock(m_TextCriticalSection);
                    sText = m_sText;
                    m_sText.Empty();
            }
            if(!sText.IsEmpty())
            {
                    m_TextEdit.SetValue(m_TextEdit.GetValue() + sText);
                    const INT nTextLength = m_TextEdit.GetWindowTextLength();
                    m_TextEdit.SetSel(nTextLength, nTextLength);
            }
            return 0;
    }

Здесь используются пользовательские классы (не «чистый» ATL), но я надеюсь, что вы поняли идею.

...