Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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=-1

var
 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.5 MB
Время: 0.032 c
2-1159286314
Merak
2006-09-26 19:58
2006.10.15
Определение текущей позиции потока при использовании IndyTCPser


3-1155639526
2ded
2006-08-15 14:58
2006.10.15
Сохранение результата запроса на др. машине


3-1155291808
Al_tor
2006-08-11 14:23
2006.10.15
ADOCommand или ADOQuery ?


15-1159032226
vidiv
2006-09-23 21:23
2006.10.15
Подскажите, как максимально просто сделать звонок (на дверь)...


15-1158916835
Empleado
2006-09-22 13:20
2006.10.15
Маразм крепчал?