2010-03-22 1 views
5

У меня есть простая программа Delphi, над которой я работаю, в которой я пытаюсь использовать потоки, чтобы отделить функциональность программы от ее графического интерфейса и сохранить гибкий интерфейс пользователя во время более длинных задачи и т. д. В принципе, у меня есть «контроллер» TThread и «вид» TForm. Представление знает дескриптор контроллера, который он использует для отправки сообщений контроллера через PostThreadMessage. В прошлом у меня не было проблем с использованием такой модели для форм, которые не являются основной формой, но по какой-то причине, когда я пытаюсь использовать эту модель для основной формы, цикл сообщений в потоке просто завершается.Тема сообщения Loop Hangs in Delphi

Вот мой код для цикла темы сообщений:

procedure TController.Execute; 
var 
    Msg : TMsg; 
begin 
    while not Terminated do begin 
    if (Integer(GetMessage(Msg, hwnd(0), 0, 0)) = -1) then begin 
     Synchronize(Terminate); 
    end; 

    TranslateMessage(Msg); 
    DispatchMessage(Msg); 

    case Msg.message of 
     // ...call different methods based on message 
    end; 
    end; 
end; 

Чтобы настроить контроллер, я делаю это:

Controller := TController.Create(true); // Create suspended 
Controller.FreeOnTerminate := True; 
Controller.Resume; 

Для обработки сообщений основной формой, я попытался с помощью обоих Application.Run и следующий цикл (сразу же после Controller.Resume)

while not Application.Terminated do begin 
    Application.ProcessMessages; 
end; 

Я застрял здесь - любая помощь будет очень признательна.

+1

Добро пожаловать в Stack Overflow, erikjw! Надеюсь, вы найдете хороший ответ. Быстрая заметка. Это делает ваш код труднее читать, когда вы ставите 'begin' в ту же строку, что и' do' или 'then' перед этим. Это считается хорошим стилем на C, но в Delphi большинство из нас предпочитает ставить его на свою линию, чтобы мы могли визуально отображать пары 'begin' и' end'. –

+0

Спасибо за все ответы. Я пробовал каждый из них отдельно, а также некоторые разные комбинации, и у меня все еще возникают проблемы. Когда я выполняю отладку и выполняю код в «TController.Execute», как только я перехожу на «GetMessage», независимо от того, что я передаю как hwnd, он просто не продолжает проходить цикл. Он не выполняет никаких инструкций после цикла, он просто необъяснимо останавливается. И что еще более запутанно, так это то, что я не вижу никаких указаний на то, что сама нить действительно умерла. –

+0

Вы пытались удалить 'Synchronize()'? Если цикл сообщений не запущен, он может просто потерпеть неудачу. Кроме того, какую версию Delphi вы используете? – Nat

ответ

3

Я проверил ваш код в основном как есть, и он отлично работал. Попробуйте добавить вызов GetLastError после того, как GetMessage вернет -1, чтобы узнать, в чем проблема.

Не ясно из кода, создаете ли вы окна в потоке контроллера, но если нет, я бы предложил передать -1 вместо 0 в качестве HWND в GetMessage и удалить вызовы TranslateMessage/DispatchMessage, так как последующий оператор case должен обрабатывать любые полученные вами сообщения.

Кроме того, вам не нужно выполнять «Синхронизировать (завершать)» при ошибке. Terminate просто устанавливает для параметра «Terminated» boolean значение true, поэтому вам не нужно его синхронизировать, и вы можете так же легко использовать «Break», чтобы выйти из цикла с тем же эффектом.

0

Где «конец» для цикла while? Я думаю, что вам не хватает и конца. Так что, возможно (в зависимости от реального кода), вы застряли в бесконечном цикле while not Terminated do в одном заявлении.

+0

Thats my bad, я исправлю это в вопросе - цикл охватывает почти всю функцию. –