2012-05-21 4 views
3

Я всегда показывал такие вещи в основном потоке и использовал события, чтобы синхронизировать конец окна с потоком, чтобы сообщить ему, когда окна закрыты.Должен ли я не показывать форму или сообщение из потока?

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

procedure WaitWithMessageLoop(); 
var 
vWaitForEventHandles:array[0..1] of THandle; 
vWaitForResponse:DWORD; 
Msg: TMSG; 
begin 
vWaitForEventHandles[0] := LServiceMonitor.Handle; 
while (1=1) do 
begin 
    vWaitForResponse := MsgWaitForMultipleObjects(1, vWaitForEventHandles, FALSE, INFINITE, QS_ALLINPUT); 
    if (vWaitForResponse = WAIT_OBJECT_0 + 1) then 
    begin 
    while (PeekMessage(msg,0,0,0,PM_REMOVE)) do 
    begin 
     TranslateMessage(msg); 
     DispatchMessage(msg); 
    end; 
    end 
    else 
    if (vWaitForResponse = WAIT_FAILED) 
    then RaiseLastOSError 
    else break; 
end; 
end; 

Так что мой вопрос. Является ли такой scenerio приемлемым? Или мне нужно переместить форму для отображения в основном потоке?

Благодаря

+0

Вы не дали понять, насколько все это подходит. Где находится форма, которую вы показываете? –

+0

В настоящее время эта форма создается и отображается в виде нити. Событие, которое я жду (как указано выше), просто дает мне информацию, когда эта нить завершит свою работу. (Он также выводит сообщения для отображения сообщений, отправляемых из потока) – John

+1

Вы не можете надежно запускать формы VCL вне основного потока графического интерфейса. Даже не думай об этом. Запустите форму из основного потока графического интерфейса, как вы знаете, что вы должны делать. Я предполагаю, что код в вопросе работает в потоке? 'while 1 = 1' лучше написано' while True'. Почему цикл не прерывается, когда ожидание возвращается успешно. 'WAIT_FAILED' является критерием нечетного завершения. –

ответ

5

Вы не можете надежно запускать VCL формы вне основного графического интерфейса резьбы. Когда вы пытаетесь это сделать, это может показаться сработавшим, но в какой-то момент в будущем такой код не удастся. Скорее всего, на вашей самой важной машине клиентов, особенно критично!

VCL был разработан таким образом, что все формы VCL создаются и управляются только из основного потока графического интерфейса пользователя. Если вам нужно вызывать формы VCL, вам необходимо использовать такие инструменты, как TThread.Synchronize, чтобы убедиться, что формы созданы в потоке графического интерфейса.

+0

Остерегайтесь: в зависимости от версии Delphi, вызывая 'TThread.Synchronize' из потока, в то время как основной поток не обрабатывает сообщения, потому что он застрял в' TThread.WaitFor', вызывает тупик. Я думаю, что это Delphi 6 и выше, которые обрабатывают это правильно, и этот вопрос касается Delphi 7, поэтому он должен * просто работать, но я мог бы легко забыть о первой версии Delphi, которая позволяет это. – hvd

+0

@ hvd Хм, но все сломается, если вы вызовете «TThread.WaitFor» из основного потока графического интерфейса. –

+0

Разве этот вопрос не спрашивает именно об этом? 'WaitWithMessageLoop' вызывается из основного потока, потому что основной поток ожидает завершения другого потока. Есть некоторые случаи, когда ожидание завершения других потоков приемлемо, особенно если вы только что назвали 'TThread.Terminate' и должны ждать, пока поток не заметит. – hvd