读书人

关于线程发送消息的有关问题

发布时间: 2012-08-08 14:32:45 作者: rapoo

关于线程发送消息的问题
一个多线程程序中,一个线程里怎么“合理”发送消息呢?

举例说吧:

窗口(模态显示)
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;

读书人网 >.NET

热点推荐