Текущий архив: 2006.10.15;
Скачать: CL | DM;
ВнизCreateThread и GetMessage - error Найти похожие ветки
← →
Призрак © (2006-05-31 18:04) [0]Я создал поток с помощью CreateThread и в нём использую GetMessage. Но, как особо указано в хелпе, GetMessage может возвращать ТРИ значения - TRUE, FALSE и -1 ! Поэтому когда я пишу if GetMessage=-1 - компилер говорит что "ошибка преобразования Variant", а если обращаться с ним как с булевым - то программа вылетает, - как я понял, потому что у потока нет очереди мессаджей и возвращается этот самый -1... Что я не так делаю?
кстати, при этом если убрать GetMessage и заставить поток крутиться по кругу - то PostMessage из основного потока завершается с ошибкой 1444 "Неправильный Thread ID", хотя я проверял - он такой же что и при создании thread"а...
И ещё одна штука которая может быть имеет значение... Поток этот создаётся не в основном потоке, а в конструкторе дополнительного. сейчас покажу :)
Основной поток:thr:=TThr.Create
и потом при нажатии кнопкиif PostThreadMessage(thr.ThirdThreadHandle, WM_USER+1, 1, 1) then messagebox(0, pchar(SysErrorMessage(GetLastError) +" : "+ inttostr(thr.ThirdThreadHandle)), "Oh Shit", MB_OK);
соответственно, выскакивает мессаджбокс с надписью - "Неверный идентификатор потока команд: 96 ". В хелпе сказано - это бывает, если у потока нет очереди сообщений, и чтобы его создать - достаточно из потока обратиться к GetMessage... но при обращении к нему ошибка выскакивает...
Второй поток (НЕ тот в котором ошибка!)TThr = class(TThread)
ThirdThreadHandle: THandle;
ThirdThread: DWORD; // Кстати, интересно как это можно использовать...
constructor Create;
function ThirdThreadProc: Longint;
protected
procedure Execute; override;
end;
constructor TThr.Create;
begin
inherited Create(false);
ThirdThreadHandle:=CreateThread(nil, 256, @TPort.ThirdThreadProc, nil, 0, ThirdThread);
messagebox(0, pchar(inttostr(WriteThreadHandle)), "Thread ID", MB_OK); // Выскакивает "96"
end;
procedure TThr.Execute;
begin
repeat
if not GetExitCodeThread(ThirdThreadHandle, r) then messagebox(0, "OH SHIT"#$0D#$0A"Error stopping ThirdThread", "ERROR", MB_OK);
until r<>STILL_ACTIVE;
messagebox(0, pchar(inttostr(r)), "Result", MB_OK);
CloseHandle(ThirdThreadHandle); // Это уже неважно, потому что ThirdThread не кончится
end;
и вот третий поток:function TPort.WriteThreadProc: Longint;
var m: TMsg;
begin
result:=10; // Заранее
messagebox(0, "Started", ThirdThread", MB_OK); // Видно, что поток стартовал
repeat
if not WaitMessage then messagebox(0, "WaitMessage = false!", "Error", MB_OK);
GetMessage(m, NULL, 0, 0); // Вот она бяка...
until m.message=WM_USER+1; // Завершится как только поймает то сообщение
messagebox(0, "Finished", "ThirdThread", MB_OK); // И я это увижу
result:=m.wParam + m.lParam; // И программа увидит
end;
Ещё немного о "бяке"... Ошибка по-любому случается, хоть обращайся к нему прямо так, хоть пиши if not getmessage, хоть if getmessage=-1 (правда, в этом случае компилер сразу несовместимые типы ловит...)
Может, надо просто очередь сообщений создать?.. но как?!..
← →
begin...end © (2006-05-31 20:35) [1]> Призрак © (31.05.06 18:04)
> Поток этот создаётся не в основном потоке, а в конструкторе
> дополнительного.
А конструктор дополнительного работает в том потоке, из которого он вызывается. То есть, скорее всего, в основном. Значит, и третий поток создаётся в основном.
> if PostThreadMessage(thr.ThirdThreadHandle, WM_USER+1, 1,
> 1) then messagebox(0, pchar(SysErrorMessage(GetLastError)
> +" : "+ inttostr(thr.ThirdThreadHandle)), "Oh Shit", MB_OK)
Если сообщение послано успешно, выводим сообщение с расшифровкой GetLastError. Очень смешно.
У PostThreadMessage первый параметр -- глобальный идентификатор потока, а не его дескриптор.
> if not WaitMessage
Это зачем?
> GetMessage(m, NULL, 0, 0);
NULL? Оригинально...
> if getmessage=-1var
R: Integer;
begin
R := Integer(GetMessage(...));
case R of
0: ...; // FALSE
-1: ...; // ERROR
else
...; // NONZERO И <> -1
end
end
> Может, надо просто очередь сообщений создать?.. но как?!
Очередь сообщений создаётся автоматически при вызове GUI-функций (в том числе и GetMessage).
← →
MBo © (2006-05-31 20:54) [2]CreateThread нужно передавать поточную функцию определенного типа, а не абы что.
← →
Призрак © (2006-05-31 21:02) [3]
> Если сообщение послано успешно, выводим сообщение с расшифровкой
> GetLastError. Очень смешно.
простите, опечатка, в программе написано правильно - если НЕ успешно...
> У PostThreadMessage первый параметр -- глобальный идентификатор
> потока, а не его дескриптор.
а-а... та самая DWORD-штука, которую я думал куда девать... понятно... -_-
сейчас попробую...
ага.
1) Заменил дескриптор на идентификатор и ошибка там больше не появляется. 08-)
2) Integer(GetMessage()) ошибку не убрало, - да мне в общем-то неважно что оно возвращает... Отсюда делаю вывод что проблема в том что NULL - "оригинально". :) В хелпе написано, как я понял, что если указать NULL - то "GetMessage возвращает все мессаги которые относятся к любому из окон потока или ко всему потоку, например, отправленные через PostThreadMessage". ...Я чего-то не понимаю?? вроде как я отправляю мессаг PostThreadMessage"ем и значит надо указывать там NULL...
3) А WaitMessage нужен для того чтобы сначала подождать когда мессаг появится... а то кто его знает что будет если на пустую очередь сделать GetMessage...
← →
Призрак © (2006-05-31 21:05) [4]MBo да вроде у меня подходящая функция... или нет?.. или что-то не так?..
← →
begin...end © (2006-05-31 21:14) [5]> Призрак © (31.05.06 21:02) [3]
> Integer(GetMessage()) ошибку не убрало, - да мне в общем-
> то неважно что оно возвращает...
Странно. По исходному вопросу сложилось иное впечатление...
> и значит надо указывать там NULL
Нет, там надо указывать 0.
> А WaitMessage нужен для того чтобы сначала подождать когда
> мессаг появится...
А GetMessage не ждёт?
> а то кто его знает что будет если на пустую очередь сделать
> GetMessage...
Я уже написал в [1], что будет. При первом вызове GetMessage (или других функций, относящихся к выборке сообщений) очередь создастся.
← →
Призрак © (2006-05-31 21:32) [6]*попробовал*
УРААААА надо было 0 указать... :) А в хелпе ясно написано что NULL ! :( спасибо!..
← →
Джо © (2006-05-31 21:55) [7]> [6] Призрак © (31.05.06 21:32)
> *попробовал*
>
> А в хелпе ясно написано что NULL ! :( спасибо!..
Этот хелп подразумевает использование C++.
← →
MBo © (2006-06-01 06:56) [8]> да вроде у меня подходящая функция... или нет?..
DWORD WINAPI ThreadProc( LPVOID lpParameter);
это аналогично паскалевскому
function ThreadProc(lpParameter: Pointer): DWord; stdcall;
У тебя же использована не регулярная функция, а метод класса. По счастью, в данном случае звезды так сошлись, что, как ты говоришь, работает, но так будет не всегда...
P.S. А вообще - надо ли смешивать VCL-ные методы работы с потоками (TTHread) и апишные (CreateThread)?
P.P.S. Да и вместо CreateThread обычно стоит использовать BeginThread
Страницы: 1 вся ветка
Текущий архив: 2006.10.15;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.064 c