Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2006.10.15;
Скачать: [xml.tar.bz2];

Вниз

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 вся ветка

Форум: "WinAPI";
Текущий архив: 2006.10.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.042 c
2-1159533557
KyRo
2006-09-29 16:39
2006.10.15
Открывается ли файл


15-1158819603
Layner
2006-09-21 10:20
2006.10.15
Браузер COM объектов установленых в системе


2-1159419736
aht
2006-09-28 09:02
2006.10.15
Дабл клик на гриде


2-1159128425
Vovan#1
2006-09-25 00:07
2006.10.15
И всё-таки он бажный (про одно предупреждение)


2-1159540488
Весь в делах
2006-09-29 18:34
2006.10.15
Иконки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский