2013-06-27 3 views
5

У меня есть большое приложение на основе MFC, которое включает некоторые потенциально очень медленные задачи в основном потоке. Это может показать, что приложение зависло, когда оно действительно прокладывает себе путь через долгую задачу. С точки зрения удобства использования я хотел бы дать пользователю дополнительную информацию о прогрессе и иметь возможность прервать задачу в чистом виде. Хотя удержание длинных задач в отдельных потоках было бы лучшим долгосрочным решением, я думаю, что прагматичное краткосрочное решение - создать новый поток GUI, инкапсулированный в свой собственный объект, в комплекте с диалогом, включающим индикатор выполнения и кнопку отмены, используемую в аналогично объекту CWait. Основной поток контролирует статус отмены с помощью метода IsCancelled и заканчивается с помощью броска, когда это необходимо.Могу ли я иметь несколько потоков графического интерфейса в MFC?

Является ли это разумным подходом, и если да, то есть какой-то код MFC, который уже есть, или я должен использовать его самостоятельно? Первый эскиз выглядит следующим образом

class CProgressThread : public CWinThread 
{ 
public: 
    CProgressThread(int ProgressMax);  
    ~CProgressThread() 
    void SetProgress(int Progress); 
    BOOL IsCancelled(); 
private: 
    CProgressDialog *theDialog; 
} 

void MySlowTask() 
{ 
    CProgressThread PT(MaxProgress); 
    try 
    { 
     { 
      { // deep in the depths of my slow task 
       PT.SetProgress(Progress); 
       if (PT.IsCancelled()) 
       throw new CUserHasHadEnough; 
      } 
     } 
    } 
    catch (CUserHasHadEnough *pUserHasHadEnough) 
    { 
     // Clean-up 
    } 
}  

Как правило, я, как правило, имеет один GUI поток и много рабочих потоков, но этот подход мог бы спасти меня кучу рефакторинга и тестирование. Любые серьезные потенциальные проблемы?

+0

dupe of http://stackoverflow.com/questions/266300/2008-mfc-and-threads? –

+0

@Balog Pal, спасибо за ссылку, но на самом деле она не придумала ничего убедительного, и на этом этапе тоже пять лет. Я много использую потоки с MFC без каких-либо проблем, просто они все рабочие потоки. –

+1

Рабочие потоки отлично работали с самого начала. Я никогда не осмеливался возиться с единственной нитью UI :). Эта тема охватывает «новую» MFC. С тех пор я не знаю значительных изменений. –

ответ

2

Короткий ответ, да, вы можете иметь несколько потоков GUI в MFC. Но вы не можете получить доступ к компоненту графического интерфейса напрямую, кроме созданного потока. Причина в том, что Win32 под MFC хранит обработчик GUI на поток. Это означает, что обработчик в одном потоке не отображается в другом потоке. Если вы перейдете к исходному коду CWinThread, вы можете найти там атрибут карты обработчика.

Windows (MFC) не имеет особого различия между рабочим потоком & GUI thread. Любой поток может быть изменен на поток GUI после создания очереди сообщений, которая создается после первого вызова, связанного с сообщением, такого как GetMessage().

В приведенном выше коде, если индикатор выполнения создается в одном потоке, а MySlowWork() вызывается в другом потоке. Вы можете использовать атрибуты CProgressThread, не касаясь функций, связанных с Win32 GUI, таких как close, setText, SetProgress ... поскольку им всем нужен GUI-обработчик. Если вы вызываете эту функцию, ошибка не сможет найти указанное окно, поскольку этот обработчик не находится в отображении обработчика потоков.

Если вам нужно изменить GUI, вам нужно отправить сообщение этому потоку владельца строки выполнения. Пусть этот поток обрабатывает сообщение сам по себе (обработчик сообщений) через PostThreadMessage, refer to MSDN for detail.