【转载】Delphi7从子线程中发送消息到主线程触发事件执行
在对数据库的操作时,有时要用一个子线程来进行后台的数据操作。比如说数据备份,转档什么的。在主窗口还能同是进行其它操作。而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上(可视),同时进行日志处理等。我用的是下面的方法:
[1]用到的API函数:
RegisterWindowsMessage
----------------------
函数功能:该函数定义一个新的窗口消息,该消息确保在系统中是唯一的。返回的消息值可在调用函数SendMessage或PostMessage时使用。
function RegisterWindowMessage(lpString: PChar): UINT; stdcall;
SendNotifyMessage
----------------------
函数功能:该函数将指定的消息发送到一个窗口。
如果该窗口是由调用线程创建的;此函数为该窗口调用窗口程序,
并等待窗口程序处理完消息后再返回。
如果该窗口是由不同的线程创建的,此函数将消息传给该窗口程序,
并立即返回,不等待窗口程序处理完消息。
SendNotifyMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
BroadcastSystemMessage
----------------------
函数功能:该函数发送消息给指定的接受者。
接受者可以是一个应用程序、安装驱动器、网络驱动器、系统级设备驱动器
或这些系统组件的组合。
[2]过程:
type
TForm1 = class(TForm)
...............
...............
private
Msg: Cardinal;
protected
procedure WndProc(var Message: TMessage); override;
public
...............
...............
end;
var
Form1: TForm1;
MsgStrList: TStringList;
MsgStrLock : TCriticalSection;
implementation
uses ThreadCommunication_Unit;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Msg := RegisterWindowMessage('wm_threadmsg');
MsgStrList := TStringList.Create;
end;
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = Msg then begin
MsgStrLock.Enter;
if MsgStrList.Count > 0 then begin
Caption := MsgStrList.Strings[0];
MsgStrList.Delete(0);
end;
MsgStrLock.Leave;
ShowMessage('收到消息了'+ inttostr(Message.Msg));
end
else begin
inherited;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TThreadCommunication.Create(Msg,Memo1);
end;
...............
...............
initialization
MsgStrLock := TCriticalSection.Create;
finalization
MsgStrLock.Free;
end.
一个子线程类的单元:
unit ThreadCommunication_Unit;
interface
uses
Classes,StdCtrls;
type
TThreadCommunicaiton = class(TThread)
private
FMsg : Cardinal;
FMemo: TMemo;
protected
procedure Execute; override;
procedure SendMsg;
public
constructor Create(aMsg:Cardinal;am:TMemo);virtual;
end;
implementation
uses Messages,Windows, Dialogs,SysUtils, ThreadMsg;
{ TThreadCommunicaiton }
constructor TThreadCommunicaiton.Create(aMsg: Cardinal; am:TMemo);
begin
inherited Create(True);
FMsg := aMsg;
FMemo:= am;
FreeOnTerminate :=True;
Resume;
end;
procedure TThreadCommunicaiton.Execute;
begin
Synchronize(SendMsg);
end;
procedure TThreadCommunicaiton.SendMsg;
var
M: TMessage;
B: DWord;
d: integer;
begin
{ Place thread code here }
sleep(50);
M.Msg := FMsg;
B := BSM_ALLCOMPONENTS;
MsgStrLock.Enter;
MsgStrList.Add('子线程子柄:'+inttostr(ThreadID)+ ' 用BroadcastSystemMessage发送');
d := MsgStrList.Count;
MsgStrLock.Leave;
BroadcastSystemMessage(BSF_POSTMESSAGE, @B , M.Msg, M.WParam, M.LParam );
FMemo.Lines.Add('子线程子柄:'+inttostr(ThreadID)+ ' 用BroadcastSystemMessage发送'+inttostr(d));
end;
end.
我在窗口上放有一Memo控件,可以显示一些信息。
同时我定义了一个全局的TStringList的变量,用于存在要从子线程传出的一些值。用BroadcaseSystemMessage发送消息,而消息号由创建子线程时传入。而消息号在FormCreate中用RegisterWindowsMessage定义,并获得一个消息号。
而消息触发后的事件处理写在WndProc中。
这里将子线程传出的字符串写入窗口的标题。
而TStringList的变量作为临界区使用, 因为当两个线程访问全局量时,为防止它们同时执行,需要使用线程同步。
用TCriticalSection进行操作。
Enter,进入临界区
Leave,离开临界区
这样可以正确的处理从子线程发来的消息。
如果是用SendNotifyMessage函数发送消息的话。
用法如下:
M.Msg := FMsg;
SendNotifyMessage(HWND_BROADCAST,M.Msg , M.WParam, M.LParam);
参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
由于是用SendNotifyMessage将消息发送到主窗口,而主窗口所在线程与调用线程是同一个线程,所以要等待窗口程序处理完消息后再返回。才会执行子线程中的:
FMemo.Lines.Add('子线程子柄:'+inttostr(ThreadID)+ ' 用SendNotifyMessage发送');
还可以用
function PostMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;
hWnd是窗口句柄,你可以将消息发送到主窗口。
而SendNotifyMessage是将消息发送到所有的顶层窗口。就是说如果你在系统中启动了两个实例运行。
一个中发出的消息两个实例都会收到。而PostMessage由于是对句柄发消息。只会在本身这个实例中产生作用。
【转载】Delphi7从子线程中发送消息到主线程触发事件执行的更多相关文章
- Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)
keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...
- GCD多线程 在子线程中获取网络图片 在主线程更新
子线程中得所有数据都可以直接拿到主线程中使用 //当触摸屏幕的时候,从网络上下载一张图片到控制器的view上显示 -(void)touchesBegan:(NSSet *)touches withEv ...
- 在子线程中发送短信,静态注册SentMsgReceiver。
1. 应该在子线程中执行发送短信的操作. 如果没有在子线程中发送短信会出现错误:点击发送短信之后,立即跳转到其他界面,那么这次发送短信可能就会失败! 请注意往子线程方法中传入外部的实参必须由final ...
- Python开发【笔记】:关于子线程(子进程)与主线程(主进程)的关联
前言: 主要分析下面的问题: 主线程启线程 主线程执行完毕,会关闭子线程吗? 子线程启线程 主线程执行完毕,会结束吗? 主进程启动进程,主进程执行完毕,会怎样? 子进程启动进程,进程执行完毕,又会 ...
- JAVA可阻塞队列-ArrayBlockingQueue子类BlockingQueue的应用,使用它来实现子线程打印10次,主线程打印100次,如此反复
/** * 使用BlockingQueue实现主子线程互相打印 * @author duwenlei * */ public class BlockingQueueTest { public stat ...
- Java面试&编写程序:使子线程循环10次,紧接着主线程循环100次,来回50次
package com.cwcec.test; public class TraditionalThreadCommunication { /** * @param args */ public st ...
- (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
来自知乎:https://www.zhihu.com/question/48130951?sort=created 大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...
- 【第三篇】学习 android 事件总线androidEventbus之发布事件,子线程中接收
发送和接收消息的方式类似其他的发送和接收消息的事件总线一样,不同的点或者应该注意的地方: 1,比如在子线程构造方法里面进行实现总线的注册操作: 2,要想子线程中接收消息的功能执行,必须启动线程. 3, ...
- iOS开发之线程间的MachPort通信与子线程中的Notification转发
如题,今天的博客我们就来记录一下iOS开发中使用MachPort来实现线程间的通信,然后使用该知识点来转发子线程中所发出的Notification.简单的说,MachPort的工作方式其实是将NSMa ...
随机推荐
- matlab列优先与高维矩阵重构 及 CNN 逐层可视化 on Matlab
由于matlab在列化a(:)以及reshape(a)等操作中是列优先的,所以要重构出新的高维度矩阵,通常要把reshape和permute结合起来使用. 先到 http://caffe.berkel ...
- ajax请求cookie有效性问题验证
与人讨论时遇到一个问题,就是: 浏览器中后台发起的一个异步ajax请求,服务器做响应时,附带了cookie信息,那么后续对同域名下其他页面请求时,该cookie是否有效,会一并随请求提交到web服务器 ...
- Halcon pick_and_place_scara_stationary_cam.hdev程序学习
此示例显示如何基于由SCARA手眼校准确定的校准信息,使用SCARA机器人执行拾取和放置应用程序. 在第一步骤中,根据模型图像定义形状模型. 然后,基于该形状模型,在每个图像中搜索对象. 对于一个选定 ...
- Eclipse/IDEA使用小技巧
使用IDEA,先将keymap改为eclipse形式 1.搜索技巧: f4:列举所有类树状结构 Ctrl+F:搜索特定词 Ctrl+T:列举所有子类 Ctrl+O:快速检索想要的方法 Ctrl+Shi ...
- iOS 9正式版开始推送 升级机型非常广泛
北京时间今日零时,苹果正式推送了iOS9,对于iPhone和iPad来说这一版系统升级都有很多重要改进,而升级的机型也非常宽泛,甚至连2011年的iPad 2与iPhone 4s都获得了支持,所以广大 ...
- Java EE-Eclipse 运行Jsp项目遇到的几个问题及解决方法
1.导入sql包错误 解决办法: 点击项目右击Properties->Java Build Path —> Libraries—>JRE System Library –> E ...
- vs2010配置boost编程环境(照抄并简化)
第一步:下载boost,我下载的方法是从http://www.boost.org/上找最新的下载.名字叫boost_1_50_0.7z. 第二步:在D盘(我C盘空间不大,准备出至少10G的空间吧)创建 ...
- [摘抄]iOS App icon、启动页、图标规范
以下内容都是我在做App时通过自己的经验和精品的分析得来的,希望会帮助到你.但是有时个别情况也要个别分析,要活学活用. 一. App Icon 在设计iOS App Icon时,设计师不需要切圆角, ...
- Static List
Static ListStatic List is the smart implementation of list data structure for those languages that h ...
- Win32隐藏输出console窗口
#include <Windows.h> void HideConsole() { ::ShowWindow(::GetConsoleWindow(), SW_HIDE); } void ...