在对数据库的操作时,有时要用一个子线程来进行后台的数据操作。比如说数据备份,转档什么的。在主窗口还能同是进行其它操作。而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上(可视),同时进行日志处理等。我用的是下面的方法:

[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从子线程中发送消息到主线程触发事件执行的更多相关文章

  1. Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

    keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...

  2. GCD多线程 在子线程中获取网络图片 在主线程更新

    子线程中得所有数据都可以直接拿到主线程中使用 //当触摸屏幕的时候,从网络上下载一张图片到控制器的view上显示 -(void)touchesBegan:(NSSet *)touches withEv ...

  3. 在子线程中发送短信,静态注册SentMsgReceiver。

    1. 应该在子线程中执行发送短信的操作. 如果没有在子线程中发送短信会出现错误:点击发送短信之后,立即跳转到其他界面,那么这次发送短信可能就会失败! 请注意往子线程方法中传入外部的实参必须由final ...

  4. Python开发【笔记】:关于子线程(子进程)与主线程(主进程)的关联

    前言: 主要分析下面的问题: 主线程启线程  主线程执行完毕,会关闭子线程吗? 子线程启线程  主线程执行完毕,会结束吗? 主进程启动进程,主进程执行完毕,会怎样? 子进程启动进程,进程执行完毕,又会 ...

  5. JAVA可阻塞队列-ArrayBlockingQueue子类BlockingQueue的应用,使用它来实现子线程打印10次,主线程打印100次,如此反复

    /** * 使用BlockingQueue实现主子线程互相打印 * @author duwenlei * */ public class BlockingQueueTest { public stat ...

  6. Java面试&编写程序:使子线程循环10次,紧接着主线程循环100次,来回50次

    package com.cwcec.test; public class TraditionalThreadCommunication { /** * @param args */ public st ...

  7. (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?

    来自知乎:https://www.zhihu.com/question/48130951?sort=created   大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...

  8. 【第三篇】学习 android 事件总线androidEventbus之发布事件,子线程中接收

    发送和接收消息的方式类似其他的发送和接收消息的事件总线一样,不同的点或者应该注意的地方: 1,比如在子线程构造方法里面进行实现总线的注册操作: 2,要想子线程中接收消息的功能执行,必须启动线程. 3, ...

  9. iOS开发之线程间的MachPort通信与子线程中的Notification转发

    如题,今天的博客我们就来记录一下iOS开发中使用MachPort来实现线程间的通信,然后使用该知识点来转发子线程中所发出的Notification.简单的说,MachPort的工作方式其实是将NSMa ...

随机推荐

  1. 转载:Android横屏竖屏切换的问题

    一.禁止横竖屏转换 Android横竖屏切换在手机开发中比较常见,很多软件在开发过程中为了避免横竖屏切换时引发不必要的麻烦,通常禁止掉横竖屏的切换, 通过在AndroidManifest.xml中设置 ...

  2. Java语言概要

    Java把源代码(SourceCode)翻译成字节码(ByteCode):javac MyClass.java,再在Java虚拟机(JVM)上执行字节码:java MyClass. Java是基于面向 ...

  3. caffe 安装资料整理

    最近在安装caffe,因为过程繁琐,而且不同的作者给出了不同的安装教程,鱼龙混杂,所以做了个简单的整理. 基本安装方法在下面博客上面都有详细介绍,不过不同版本的硬件适配不同版本的软件,所以安装的时候一 ...

  4. folly::AtomicHashmap源码分析(二)

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ 背景 上一篇只是细致的把源码分析了一遍,而源码背后的设计思想并没有写,设计思想往往是最重要的,没有它,基本无法做整 ...

  5. 跨服务器的session共享

    四种 一.NFS(Net FileSystem): sun公司提供的,并发处理的效率不高,但操作方便 二.基于数据库的session共享 三.基于cookie的session共享 原理:将sessio ...

  6. 移动端的拖拽这个demo实现的功能

    SQL数据库适合那些需求确定和对数据完整性要去严格的项目.NoSQL数据库适用于那些对速度和可扩展性比较看重的那些不相关的,不确定和不断发展的需求. 总所周知,网页的加载速度跟图片是有很大的关系的,因 ...

  7. Android使用AudioTrack发送红外信号

    最近要做一个项目,利用手机的耳机口输出红外信号,从而把手机变成红外遥控器,信号处理的知识基本都还给老师了,刚开始真的挺头疼.找了不少资料研究了一下,总算有点心得,在这里做个备忘. 一.音频信号输出原理 ...

  8. php部分,一个用递归无限分类的方法

    <?php $data[]=array('id'=>1,'parentid'=>0,'name'=>'中国'); $data[]=array('id'=>2,'paren ...

  9. chrome浏览器定位页面元素对应代码查找资源

    F12 左边箭头或ctrl shift c 点击相应元素即可定位代码 应用:定位flash游戏代码后,鼠标移至带下划线链接处右键copy link

  10. install vim

    常用命令: [0]安装vim: oee@copener:~$ sudo apt-get install vim vim-scripts vim-doc 刚安装完$HOME目录下只有两个文件:.vim/ ...