Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.11.23;
Скачать: CL | DM;

Вниз

Отловить сообщение во втором потоке созданным CreateThread   Найти похожие ветки 

 
Black_Tomcat   (2007-12-26 07:08) [0]

Здравствуйте.
Подскажите пожалуйста как отправить сообщение во второй поток и как его там поймать. А то, я что запутался окончательно вроде отправка осуществляется при помощи функции PostThreadMessage, а прием PeekMessage. Но вот только PostThreadMessage возвращает False, a GetLastError 1159. Что я не так делаю?


 
Сергей М. ©   (2007-12-26 08:34) [1]

Что говорит SysErrorMessage(GetLastError) ?


 
Black_Tomcat   (2007-12-26 09:19) [2]


> Что говорит SysErrorMessage(GetLastError) ?


"Сообщение может быть использовано только с операциями синхронизации"
А что это значит?


 
Сергей М. ©   (2007-12-26 09:27) [3]

А какое конкретно сообщение ты посылаешь ?


 
Black_Tomcat   (2007-12-26 09:35) [4]

var
Data:tagCOPYDATASTRUCT;

PostThreadMessage(ThreadID,WM_COPYDATA,0,lParam(@Data));


 
Сергей М. ©   (2007-12-26 09:38) [5]

Тогда отлуп ты получаешь вполне резонно - сообщение с кодом WM_COPYDATA есть специальный зарезервированный вид сообщения, которое можно отправлять только синхронно, т.е. с использованием SendMessage, а не Post[Thread]Message


 
Black_Tomcat   (2007-12-26 09:43) [6]

Ясно спасибо.
А как его отловить во втором потоке?


 
Сергей М. ©   (2007-12-26 09:47) [7]

Прежде чем его "ловить" нужно осознать, что ф-ция SendMessage подразумевает адресатом окно (или окна) , а не нить. Целевая нить у тебя создает хоть одно окно ?


 
Black_Tomcat   (2007-12-26 09:53) [8]

Это я знаю :-)
Окно у меня есть. И оно умеет обрабатывать это сообщение. Мне нужно его как-то перехватить перед тем как окно его обработает. Это возможно?


 
Сергей М. ©   (2007-12-26 10:11) [9]


> Окно у меня есть


Оно откуда взялось ? Его какая нить создала - целевая ?


 
Black_Tomcat   (2007-12-26 10:17) [10]

Я пишу на VCL окно стандартное.
Целевая нить и основной поток это одно и тоже?


 
Сергей М. ©   (2007-12-26 10:20) [11]

Поток (кодовый) = нить = тред = thread.

Если ты отправляешь сообщение основному потоку, то разумеется он является целевым потоком.


 
Сергей М. ©   (2007-12-26 10:22) [12]

Определись, кому ты посылаешь сообщение - потоку или окну..


 
Black_Tomcat   (2007-12-26 10:30) [13]

Мне нужно отправить это сообщение в созданный поток.
И из созданного потока обратно окну.
Oкну можно его отправить  например так SendMessage(Form1.Handle,WM_COPYDATA,0,lParam(i)) .

Но вот как отправить это сообщение в созданный мною поток? И как его там обработать, я не могу понять.
Может ли мною созданный поток, выгребать сообщения из очереди сообщений окна?


 
Сергей М. ©   (2007-12-26 10:47) [14]


> как отправить это сообщение в созданный мною поток?


Никак. Только окну его можно отправить.
Меняй концепцию и логику.


> Может ли мною созданный поток, выгребать сообщения из очереди
> сообщений окна?


А собссно зачем ? Поясни ..


 
Black_Tomcat   (2007-12-26 10:53) [15]

Я отправляю сообщение окну.
Поток его забирает из очереди собщений, например занимает семафор, а процедура обработки сообщения целевого потока в зависимости от состояния семаформа решает обрабатывать его или нет.
Или я вообще неправильно думаю.


 
Сергей М. ©   (2007-12-26 11:02) [16]


> Поток его забирает из очереди собщений


Его забирает тот поток, который создал окно, т.е. в твоем случае основной.

Далее этот поток смотрит на семафор - если он занят, то делает с полученным сообщением одно действие , иначе другое.


 
Black_Tomcat   (2007-12-26 11:07) [17]

Спасибо.
Теперь пойду валить препода. :-)


 
Сергей М. ©   (2007-12-26 11:23) [18]


> пойду валить препода


Как бы он тебя не завалил)


 
Black_Tomcat   (2007-12-28 10:45) [19]

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

unit Unit1;

var Thread2:THandle;
FormThread2:HWND;

Procedure Query;

function SecondWinProc (hWnd: THandle; nMsg: UINT;wParam, lParam: Cardinal): Cardinal; export; stdcall;
begin
 if nMsg=WM_COPYDATA then
   //do something
  else
   if nMsg=WM_SEND_DATA then
     //do something
end;

var xPos,yPos,nWidth,nHeight : Integer;
var wc : TWndClassEx;
Msg : TMsg;
begin
wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@SecondWinProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=Thread2;
wc.hIcon:=LoadIcon(0,idi_application);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:="SecondForm";

RegisterClassEx(wc);
xPos:=0;
yPos:=0;
nWidth:=0;
nHeight:=0;
FormThread2:=CreateWindowEx(
                           0,
                           "SecondForm",
                           "SecondForm",
                           ws_overlappedwindow,
                           xPos,
                           yPos,
                           nWidth,
                           nHeight,
                           0,
                           0,
                           Thread2,
                           nil
                           );

While GetMessage(Msg,FormThread2,0,0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Thread2:=CreateThread(nil,2048,@Query,nil,0,ThreadID2);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
     SendMessage(FormThread2,WM_COPYDATA,0,lParam(123));
     SendMessage(FormThread2,WM_COPYDATA,0,Integer(321));
end;


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


 
Сергей М. ©   (2007-12-28 10:50) [20]


> функция обработки сообщений созданного окна выполняется
> в основном потоке


Ничего подобного.
Оконная функция выполняется в потоке, создавшем окно.


 
Сергей М. ©   (2007-12-28 10:57) [21]

Почему вообще WinAPI ?
Это блажь или учебная задача ?
Если блажь, то чья - твоя или препода ?
Если учебная задача, то не рановато ли при таких знаниях "валить препода" ?)


 
Black_Tomcat   (2007-12-28 11:12) [22]

Я проверял в режиме отладки эта функция почему-то выполняется основном потоке есть, еще одно подтверждение

var list:Array of integer;
Data:tagCOPYDATASTRUCT;
begin
Data.dwData:= 123;
Data.cbData:= Length(List)*4;
Data.lpData:=@list;
SendMessage(FormThread2,WM_COPYDATA,wParam(@list),lParam(@data));

wParam передает не указатель отправляемому окну равный тому который я передавал и он рабочий, a lParam предает модифицированный указатель предназначенный второму потоку, но при обращении к нему я не могу ничего получить.
А WinAPI это задание на курсач типа как для ознакомления с ним, и что они вообще есть.
А знания препода оставляют желать лучшего как вам задание передача данных меджу потоками через сообщения. И синхронизация с помощью семафора?


 
Сергей М. ©   (2007-12-28 11:22) [23]

type

TMyThread = class(TThread)
private
 FhWnd: THandle;
 procedure ThreadWndProc(var Message: TMessage);
 procedure MsgWmCopydata(var Msg: TWMCopyData); message WM_COPYDATA;
 procedure MsgWmSendata(var Msg: TWMSendData); message WM_SEND_DATA;
..
protected
 procedure Execute; override;
..
end;

..

procedure TMyThread.MsgWmCopydata(var Msg: TWMCopyData);
begin
 .. обработка сообщения WM_COPYDATA ..
end;

procedure TMyThread.MsgWmSendata(var Msg: TWMSendData);
begin
 .. обработка сообщения WM_SEND_DATA ..
end;

procedure TMyThread.ThreadWndProc(var Message: TMessage);
begin
 Dispatch(Message);
end;

procedure TMyThread.Execute;
var
 Msg: TMsg;
begin
 FhWnd := AllocateHWnd(ThreadWndProc);
 try
   while not Terminated and GetMessage(Msg, 0, 0, 0) do
      DispatchMessage(Msg);
 finally
   DeallocateHWnd(FhWnd);
 end;
end;


 
Black_Tomcat   (2007-12-28 11:30) [24]

Я бы с удовольствием сделал через класс потока, но нельзя.
Спасибо.
Теперь буду докуривать Джеффри Рихтера, и Windows SDK.
Еще раз спасибо.


 
Сергей М. ©   (2007-12-28 11:34) [25]


> wParam передает не указатель отправляемому окну равный тому
> который я передавал


wParam на момент вызова SensMessage должно содержать хэндл окна-"оптавителя", а ты в этом параметре передаешь черт те что, но только не хэндл окна.


> lParam предает модифицированный указатель


Никакой он не "модифицированный". Обычный указатель на COPYDATASTRUCT-структуру в адресном пространстве процесса-отправителя.
А в адресном пространстве процесса-получателя полученный lParam будет содержать совершенно другой указатель на принятую структуру, и это абсолютно нормально - адресные пространства процессов абсолютно изолированы друг от друга.


 
Сергей М. ©   (2007-12-28 11:36) [26]


> с удовольствием сделал через класс потока, но нельзя


Да на здоровье. Нельзя так нельзя. Пользуй BeginThread().


 
Сергей М. ©   (2007-12-28 11:58) [27]

Вот тебе тоже самое, но без TThread:

type

TMyThread = class(TObject)
private
FhWnd: THandle;
procedure ThreadWndProc(var Message: TMessage);
procedure MsgWmCopydata(var Msg: TWMCopyData); message WM_COPYDATA;
procedure MsgWmSendata(var Msg: TWMSendData); message WM_SEND_DATA;
..
end;

..

procedure TMyThread.MsgWmCopydata(var Msg: TWMCopyData);
begin
.. обработка сообщения WM_COPYDATA ..
end;

procedure TMyThread.MsgWmSendata(var Msg: TWMSendData);
begin
.. обработка сообщения WM_SEND_DATA ..
end;

procedure TMyThread.ThreadWndProc(var Message: TMessage);
begin
Dispatch(Message);
end;

function MyThreadFunc(MyThreadObject: TMyThread): Integer;
var
Msg: TMsg;
begin
with MyThreadObject do
begin
FhWnd := AllocateHWnd(ThreadWndProc);
try
  while GetMessage(Msg, 0, 0, 0) do
     DispatchMessage(Msg);
finally
  DeallocateHWnd(FhWnd);
end;
end;
end;

..  
 
BeginThread(nil, 0, @MyThreadFunc, Pointer(TMyThreadObject.Create), MyThreadId);


 
MetalFan ©   (2007-12-28 14:03) [28]

а зачем AllocateHWND???


 
MetalFan ©   (2007-12-28 14:03) [29]

а, ну да... тут же WM_COPYDATA


 
Black_Tomcat   (2008-01-18 09:51) [30]

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


function WindowThreadProc(WND:HWND; Msg : Integer; wParam:Wparam;
lParam:Lparam):Longint; stdcall; export;
begin
 if Msg=WM_COPYDATA then
   begin
        //что-нибудь делаем
   end
end;

//второй поток
Function Query:DWORD;
var i:integer;
Msg:TagMSG;
 WndClassEx: TWndClassEx;
   PQRec:PQueryRecord;
begin
FormThread2 := CreateWindowEx (
     ws_Ex_OverlappedWindow,
     "Message",//Специальный класс окна для обмена сообщениями
     "Plain API Demo",
     ws_OverlappedWindow,
     cw_UseDefault, 0,
     cw_UseDefault, 0,
     0,
     0,
     Thread2,
     nil);
   if FormThread2 = 0 then
     MessageBox (0, "Window not created",
       "Plain API", MB_OK);
//заменяю процедуру обработки сообщений окна
SetWindowLong(FormThread2,GWL_WNDPROC,integer(@WindowThreadProc));
while GetMessage(Msg,FormThread2,0,0) do
 begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
 end;
end;



 
Сергей М. ©   (2008-01-18 12:57) [31]


> TranslateMessage(Msg);


Эт лишнее.


 
Slym ©   (2008-01-18 13:28) [32]

Black_Tomcat   (18.01.08 9:51) [30]
не забываем про DefWindowProc!
function WindowThreadProc(WND:HWND; Msg : Integer; wParam:Wparam;
lParam:Lparam):Longint; stdcall; export;
begin
if Msg=WM_COPYDATA then
  begin
       //что-нибудь делаем
  end
 else
 result:=DefWindowProc(WND,Msg,wParam,lParam);
end;


 
Black_Tomcat   (2008-01-18 13:29) [33]

Еще раз спасибо.
Запомню.



Страницы: 1 вся ветка

Текущий архив: 2008.11.23;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.015 c
15-1222328712
nick
2008-09-25 11:45
2008.11.23
нужна помощь


2-1223625754
asders
2008-10-10 12:02
2008.11.23
HotKey


15-1222252560
DelphiN!
2008-09-24 14:36
2008.11.23
Объединение 2х сетей в одну


15-1222450529
No_Dead(work)
2008-09-26 21:35
2008.11.23
зачем нужен *.ion?


2-1223819376
lewka
2008-10-12 17:49
2008.11.23
WebBrowser