Ik had ook verwacht dat het zou hangen, maar dat is niet het geval. In plaats daarvan komt SendMessage gewoon terug. Wellicht zit er ergens een bescherming om dit te voorkomen, maar het werkt inderdaad niet.
Vanuit een thread zou het inderdaad wel werken, alleen als je een thread of task maakt, en daar direct op wacht na het starten, dan zal je code alsnog hangen. Dan gebeurt er eigenlijk wat Rik en ik voorspelden. Eventueel resultaat van de SendMessage zal je dus ook binnen de thread of task moeten verwerken, en eventueel synchronizen als dat nodig is. Hierbij 4 button clicks, waarbij m.i. de laatste de enige juiste is (van deze, er zijn vast nog andere manieren).
Delphi Code:
procedure TForm3.Button1Click(Sender: TObject);
begin
// ShowMessage wordt bereikt, maar de hele message naar application lijkt verdwenen
SendMessage(Application.Handle, WM_DESTROY, 0, 0);
Showmessage('done!' + (WM_USER+1).ToString);
end;
procedure TForm3.Button2Click(Sender: TObject);
var
t: ITask;
begin
t := TTask.Create(
procedure
begin
// Message wordt verstuurd, doordat hij nu uit een andere thread verstuurd wordt.
SendMessage(Application.Handle, WM_DESTROY, 0, 0);
end);
t.Start.Wait; // Dit blokkeert, omdat de applicatie nooit de message verwerkt, en de thread dus nooit afgerond wordt. De applicatie hangt.
Showmessage('done!' + (WM_USER+1).ToString);
end;
procedure TForm3.Button3Click(Sender: TObject);
var
t: ITask;
begin
t := TTask.Create(
procedure
begin
// Message wordt verstuurd, doordat hij nu uit een andere thread verstuurd wordt.
SendMessage(Application.Handle, WM_DESTROY, 0, 0);
// Message wordt getoond vanuit de thread. Dit lijkt te werken, maar is volgens mij
// een risico, omdat dit een VCL form gebruikt, wat niet thread safe is. Als jouw code daar niet gevoelig voor is, is dat natuurlijk geen probleem.
Showmessage('done!' + (WM_USER+1).ToString);
end);
t.Start;
end;
procedure TForm3.Button4Click(Sender: TObject);
var
t: ITask;
begin
t := TTask.Create(
procedure
begin
// Message wordt verstuurd, doordat hij nu uit een andere thread verstuurd wordt.
SendMessage(Application.Handle, WM_DESTROY, 0, 0);
// Het tonen van de message (of eventueel andere niet-threadsafe opvolging)
// wordt gesynct met de main thread.
TThread.Synchronize(TThread.Current,
procedure
begin
Showmessage('done!' + (WM_USER+1).ToString);
end);
end);
t.Start;
end;
E.e.a in een testproject dat de ontvangen message ook laat zien.
MsgDemo.zip
Bookmarks