多线程同步

利用主线程与子线程间的消息通讯,实现任务处理队列

WaitForMultipleObject与MsgWaitForMultipleObjects用法 .

PeekMessage和GetMessage函数的主要区别


CSDN上的同步小Demo:

主线程:

unit Unit1;

interface
uses
  LongWaitTrd,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btnSetTask: TButton;
    btnExitThd: TButton;
    btnCreateTrd: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Button2: TButton;
    Button1: TButton;
    Edit2: TEdit;
    Label2: TLabel;
    procedure btnSetTaskClick(Sender: TObject);
    procedure btnCreateTrdClick(Sender: TObject);
    procedure btnExitThdClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
     LongWaitThread:TLongWaitTrd;
     FCreationTime{线程创建时间},FExitTime{线程退出时间},
     FKernelTime{操作系统代码时间},FUserTime{应用程序本身代码时间}:TFileTime;
     procedure OnThreadMessage(var Message: TMessage); message WM_USER+2000;
     procedure OnTerminate(Sender:TObject);

     function FileTimeToDateTime(FileTime:TFileTime):TDateTime;
     Function DateTimeToFileTime(DateTime:TDateTime):TFileTime;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
implementation
{$R *.dfm}


procedure TForm1.btnSetTaskClick(Sender: TObject);
begin
//将一个消息放入(寄送)到指定线程的消息队列里,不等待线程处理消息就返回
   if (LongWaitThread<>nil) then PostThreadMessage(LongWaitThread.ThreadID,WM_USER+1000,0,0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if  LongWaitThread<>nil then
     LongWaitThread.Priority:= tpHighest;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 if  LongWaitThread<>nil then
     case LongWaitThread.Priority of
       tpIdle:edit2.Text:='tpIdle';
       tpLowest:edit2.Text:='tpLowest';
       tpLower:edit2.Text:='tpLower';
       tpNormal:edit2.Text:='tpNormal';
       tpHigher:edit2.Text:='tpHigher';
       tpHighest:edit2.Text:='tpHighest';
       tpTimeCritical:edit2.Text:='tpTimeCritical';
     end;
end;

function TForm1.DateTimeToFileTime(DateTime: TDateTime): TFileTime;
var SysTime:TSystemTime;
begin
 with SysTime do
 begin
   DecodeDate(DateTime,wYear,wMonth,wDay);
   DecodeTime(DateTime,wHour,wMinute,wSecond,wMilliseconds);
   wDayofWeek:=DayOfWeek(DateTime);
 end;
 if not SystemTimeToFileTime(SysTime,Result) then
    raise EConvertError.CreateFmt('SystemTimeToFileTime failed.'
          +'Error Code %d',[GetLastError]);
end;

function TForm1.FileTimeToDateTime(FileTime: TFileTime): TDateTime;
var SysTime:TSystemTime;
begin
  if not FileTimeToSystemTime(FileTime,SysTime) then
      raise EConvertError.CreateFmt('FileTimeToSystemTime failed.'
          +'Error Code %d',[GetLastError]);
  with SysTime do
   Result := EncodeDate(wYear,wMonth,wDay)+
   EncodeTime(wHour,wMinute,wSecond,wMilliseconds);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if LongWaitThread<>nil then
     btnExitThd.OnClick(nil);
end;

procedure TForm1.btnCreateTrdClick(Sender: TObject);
begin
if (LongWaitThread=nil) then
   begin
  LongWaitThread:=TLongWaitTrd.Create(True); //建立线程,不要立即执行
  LongWaitThread.MainWin:=Handle;    //将本身句柄传给线程
  LongWaitThread.Resume;   //开始执行
  showmessage('建立线程完成!');
  end else
  showmessage('线程已成存!');
  LongWaitThread.OnTerminate:=OnTerminate;

end;

procedure TForm1.OnTerminate(Sender: TObject);
begin
 if LongWaitThread<>nil then

  if GetThreadTimes(LongWaitThread.Handle,
                  FCreationTime{线程创建时间},
                  FExitTime{线程退出时间},
                  FKernelTime{操作系统代码时间},
                  FUserTime{应用程序本身代码时间})
  then ;
end;

procedure TForm1.OnThreadMessage(var Message: TMessage);
begin
  if Message.Msg= WM_USER+2000 then
  begin
    Showmessage(String(message.LParam));
  end;
end;

procedure TForm1.btnExitThdClick(Sender: TObject);
begin
  while True do
  Begin
    if LongWaitThread<>nil then
       begin
             if LongWaitThread.ExitLongWaitTrd() then
              begin
                LongWaitThread:=nil;
                Showmessage('LongWaitThread Over!');
                break;
              end;
       end
    else
        begin
           Showmessage('LongWaitThread不存在!');
           Break;
        end;
  end;
end;

end.
子线程:

unit LongWaitTrd;

interface
uses
  Classes,Windows,Messages,SyncObjs,SysUtils,Forms;

type
  TLongWaitTrd = class(TThread)
  private
    FMainWin:THandle;
    QuitEvent: TEvent;
    procedure  SendFeedBackToMainWin();
    procedure  DoTheHardWork();
  protected
    procedure Execute; override;  //通过消息执行任务
  public
    constructor  Create(CreateSuspended: Boolean);
    Destructor   Destroy; override;
    function     ExitLongWaitTrd():Boolean;
  published
    property MainWin:THandle read FMainWin write FMainWin;
  end;

implementation

uses Unit1;

constructor TLongWaitTrd.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
end;

destructor TLongWaitTrd.Destroy;
begin

  inherited;
end;



procedure TLongWaitTrd.DoTheHardWork();
begin
  //form1.Canvas.TextOut(10,10,FormatDateTime('hh:mm:ss',now));
   form1.Edit1.Text:=FormatDateTime('hh:mm:ss',now);
end;

procedure TLongWaitTrd.Execute;
var Msg: TMsg;
begin
  FreeOnTerminate:=True;


//1.长等待型线程示例
  while GetMessage(Msg, 0, 0, 0) do
  begin
     if (Msg.message=WM_USER+1000) then //任务来了
     begin
        DoTheHardWork();
        SendFeedBackToMainWin;
     end;
     if (Msg.message=WM_QUIT) then
     begin
        QuitEvent.SetEvent;
        Break;
     end;
  end;
// }
//2.长工作型线程示例
   while(True) do
   begin
      if  Application.Terminated then  break;
   //该函数为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构
     if  PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
     begin
        if (Msg.message=WM_QUIT) then
           begin
             QuitEvent.SetEvent;
             Break;
           end;
     end;
     DoTheHardWork();
   end;


end;

function TLongWaitTrd.ExitLongWaitTrd;
begin
  Result:=true;
  QuitEvent:=TEvent.Create(nil,True,False,'QuitEvent');
  PostThreadMessage(ThreadID,WM_QUIT,0,0);
  if  (QuitEvent.WaitFor(2000)=wrTimeOut) then
       Result:=false;
  QuitEvent.Free ;
end;

procedure TLongWaitTrd.SendFeedBackToMainWin();
var Status:String;
begin
   if (MainWin<>0) then
   begin
     Status:='The data has been processed by thread.';
     PostMessage(MainWin,WM_USER+2000,0,Integer(Status))
   end;
end;

end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值