Author: Jonas Bilinkevicius
I am using a thread that does some system checks and outputs the results to a
TRichEdit, so I need to use a Syncronize(AMethod) to update the interface and the
TRichEdit mentioned before. But I cannot do this if AMethod accepts parameters. I
would like to pass some parameters to AMethod, but have not been able to do this.
Is this possible?
Answer:
Below is the complete code to do this, using the function:
function ExecuteInMainThread(Proc: MainThreadProcType; var Parameter): boolean;
It will call Proc in the main Windows thread and wait for the procedure to finish
before returning. Proc takes one untyped variable. If you want to pass more than
one variable, put the data into a record and pass the record. You don't really have
to code anything. Just copy this code to a unit, use the unit in your code, and
call the function. There is no TThread method that does this.
1 unit ThreadLib;
2
3 interface
4
5 uses
6 Windows, Messages, ExtCtrls, Classes, Forms, SyncObjs;
7
8 type
9 MainThreadProcType = procedure(var Parameter) of object;
10
11 function ExecuteInMainThread(Proc: MainThreadProcType; var Parameter): boolean;
12
13 implementation
14
15 uses
16 SysUtils;
17
18 const
19 UM_EXECMAIN = WM_USER + 590;
20
21 type
22 WindowProcType = function(hWnd: HWND; Msg: UINT; wParam: WPARAM;
23 lParam: LPARAM): LRESULT; stdcall;
24
25 ProcInfoType = record
26 Method: MainThreadProcType;
27 Param: pointer;
28 end;
29
30 ProcInfoPtrType = ^ProcInfoType;
31
32 var
33 OrigThreadWndProc: WindowProcType;
34
35 function ExecuteInMainThread(Proc: MainThreadProcType; var Parameter): boolean;
36 var
37 ProcInfo: ProcInfoType;
38 begin
39 if GetCurrentThreadID = MainThreadID then
40 try
41 Proc(Parameter);
42 Result := true;
43 except
44 Result := false;
45 end
46 else
47 begin
48 ProcInfo.Method := Proc;
49 ProcInfo.Param := @Parameter;
50 Result := SendMessage(Application.Handle, UM_EXECMAIN, 0, longint(@ProcInfo)) =
51 ord(true);
52 {To send a message without waiting for it to return (PostMessage),
53 make sure that the message parameters do not include pointers. Otherwise,
54 the functions will return before the receiving thread has had a chance to
55 process the message and the sender will free the memory before it is used.}
56 end;
57 end;
58
59 function ParamThreadWndProc(Window: HWND; message, wParam, lParam: longint):
60 longint; stdcall;
61 begin
62 if message = UM_EXECMAIN then
63 try
64 with ProcInfoPtrType(pointer(lParam))^ do
65 Method(Param^);
66 Result := ord(true);
67 except
68 Result := ord(false);
69 end
70 else
71 Result := OrigThreadWndProc(Window, message, wParam, lParam);
72 end;
73
74 begin
75 OrigThreadWndProc := WindowProcType(SetWindowLong(Application.Handle,
76 GWL_WNDPROC, longint(@ParamThreadWndProc)));
77 end.
|