关于线程发送消息的问题
一个多线程程序中,一个线程里怎么“合理”发送消息呢?
举例说吧:
窗口(模态显示)
FormMain 主窗口
FormA
FormB
FormC
....
FormJ
线程(执行功能基本一样)
Thread1
Thread2
Thread3
.....
Thread16
消息
WM_Message001
WM_Message002
WM_Message003
.....
WM_Message006
后台线程的Execute()中:
while true do
begin
//检查线程是否要退出
.....
for i:=0 to MaxCount-1 do
begin
//如果满足了某一条件,向需要处理Message002消息的窗口发送消息
PostMessage(FMessage002Handle,WM_Message002,0,0); //FMessage002Handle是线程中一个私有变量,对应一个
//Message002Handle属性
.....
//如果满足了某一条件,向需要处理Message003消息的窗口发送消息
PostMessage(FMessage003Handle,WM_Message003,0,0); //FMessage003Handle是线程中一个私有变量,对应一个
//Message003Handle属性
.....
end;
....
//如果满足了某一条件,向所有当前窗口发送消息
PostMessage(Screen.ActiveForm.Handle,WM_Message001,0,0);
...
end;
我的问题:
这儿就有一个设置消息目的窗口句柄的问题,除了WM_Message001是所有窗口都要处理的,还有FormA要处理WM_Message002和WM_Message003,FormB要处理WM_Message002,FormC要处理WM_Message003,等等,而且这些窗口有些是模态窗口,关闭后就释放了,有些窗口关闭后只是隐藏了,未释放。
我现在的做法是,在每个窗口的OnShow事件或OnActived事件里,设置所有线程的属性Message002Handle,Message003Handle, 感觉这样好零乱,增加一个消息,线程里就得增加一个属性。这程序肯定还得变动,刚开始试用。
1、能不能在线程里全部用PostMessage(Screen.ActiveForm.Handle,WM_MessageXXX,0,0)来发送?窗口只处理自己需要处理的消息。这样会不会影响性能(大概最多会有16个线程)
2、还有个蛋疼的想法:是不是自己能再做个消息转发分配中心什么的(也就是一个线程,专门用于消息分配和转发),也就是所有线程的消息先转发到这个“消息处理线程”,然后在这里再分配发送,感觉这个“消息处理线程”有画蛇添足之嫌,而且也影响了程序性能。
大家碰到类似的问题,是怎么解决的?请指教啊
[解决办法]
1.你处理的快就不会有问题了。
很多窗口要处理就广播消息。
[解决办法]
消息发主程序,由主程序决定向哪个窗口转发:
PostMessage(Application.Handle, WM_MessageXXX, 0, 0);
[解决办法]
一个笨办法; 把你那些变量用结构体数组代替,改成全局变量
用它保存窗体的handle和窗体的关系,增加/减少窗体只要改变下标就行了
窗体打开时设置handle,关闭时设置0;线程取值时加上锁,handle不是0的就发送消息出去
[解决办法]
向主线程所有窗口广播消息
function __BroadcastMessageEnumProc(AHandle: HWND; AParam: lParam): Boolean; stdcall;
var
lpMsg: PMessage;
begin
if (AParam <> 0) and IsWindow(AHandle) then
begin
lpMsg := Pointer(AParam);
PostMessage(AHandle, lpMsg.Msg, lpMsg.wParam, lpMsg.lParam);
end;
Result := True;
end;
procedure BroadcastMessage(Msg: UINT; wParam: wParam; lParam: lParam);
var
mtid: DWORD;
lpMsg: PMessage;
begin
mtid := GetMainThreadID;
new(lpMsg);
try
lpMsg.Msg := Msg;
lpMsg.wParam := wParam;
lpMsg.lParam := lParam;
EnumThreadWindows(mtid, @__BroadcastMessageEnumProc, Integer(lpMsg));
finally
Dispose(lpMsg);
end;
end;