• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

delphi把多个线程的请求阻塞到另一个线程TElegantThread

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本例是把多个线程访问数据库的请求,全部阻塞到一个线程。

这是实际编程中常见的一种问题。

示例源码下载,所需支持单元均在源码中,且附详细说明。

TElegantThread 的父类是 TSimpleThread

unit uElegantThread;

interface

uses
  Classes, SysUtils, uSimpleThread, uSimpleList, uSyncObjs;

type

  PSyncRec = ^TSyncRec;

  TSyncRec = record
    FMethod: TThreadMethod;
    FProcedure: TThreadProcedure;
    FSignal: TSuperEvent;
    Queued: boolean;
    DebugInfo: string;
  end;

  TSyncRecList = Class(TSimpleList<PSyncRec>)
  protected
    procedure FreeItem(Item: PSyncRec); override;
  End;

  TElegantThread = class(TSimpleThread)
  private
    FSyncRecList: TSyncRecList;

    procedure LockList;
    procedure UnlockList;

    procedure Check;
    procedure DoCheck;

  public

    // AAllowedActiveX 允许此线程访问 COM 如:IE ,
    // 当然,获取 Ie 的 IHtmlDocument2 接口,也必须在此线程内执行
    constructor Create(AAllowedActiveX: boolean = false);
    destructor Destroy; override;

    // ADebugInfo 是调用者用来查错用,一般可以写上过程名 如:'DoSomeThing';
    procedure Queue(AMethod: TThreadMethod; ADebugInfo: string = ''); overload;
    procedure Queue(AProcedure: TThreadProcedure; ADebugInfo: string = ''); overload;

    procedure Synchronize(AMethod: TThreadMethod; ADebugInfo: string = ''); overload;
    procedure Synchronize(AProcedure: TThreadProcedure; ADebugInfo: string = ''); overload;

  end;

implementation

{ TSyncRecList }

procedure TSyncRecList.FreeItem(Item: PSyncRec);
begin
  inherited;
  if Assigned(Item.FSignal) then
    Item.FSignal.Free;
  Dispose(Item);
end;

{ TElegantThread }

procedure TElegantThread.Check;
begin
  ExeProcInThread(DoCheck);
end;

constructor TElegantThread.Create(AAllowedActiveX: boolean);
begin
  inherited;
  FSyncRecList := TSyncRecList.Create;
end;

destructor TElegantThread.Destroy;
begin
  WaitThreadStop;
  FSyncRecList.Free;
  inherited;
end;

procedure TElegantThread.DoCheck;
var
  p: PSyncRec;
  sErrMsg: string;
begin

  LockList;
  try
    p := FSyncRecList.PopFirst; // 每次从 List 取出一个过程来执行
  finally
    UnlockList;
  end;

  if Assigned(p) then
  begin

    try

      if Assigned(p.FMethod) then
        p.FMethod // 执行
      else if Assigned(p.FProcedure) then
        p.FProcedure(); // 执行

    except
      on E: Exception do // 错误处理
      begin
        sErrMsg := 'DebugInfo:' + p.DebugInfo + #13#10;
        sErrMsg := sErrMsg + 'ErrMsg:' + E.Message;
        DoOnDebugMsg(sErrMsg);
      end;
    end;

    if not p.Queued then // 如果是阻塞,请设为有信号,调用者即可返回
    begin
      p.FSignal.SetEvent;
    end;

    Dispose(p);
    Check; // 继续下一次 DoCheck,也就是本过程。
    // 父类 TSimpleThread 已特殊处理,不会递归。

  end;

end;

procedure TElegantThread.LockList;
begin
  FSyncRecList.Lock;
end;

procedure TElegantThread.Queue(AMethod: TThreadMethod; ADebugInfo: string);
var
  p: PSyncRec;
begin
  // 此过程为排队执行

  new(p);
  p.FProcedure := nil;
  p.FMethod := AMethod;
  p.Queued := true;

  LockList;
  try
    FSyncRecList.Add(p); // 把要执行的过程加入 List
    Check; // 启动线程
  finally
    UnlockList;
  end;

end;

procedure TElegantThread.Queue(AProcedure: TThreadProcedure; ADebugInfo: string);
var
  p: PSyncRec;
begin
  new(p);
  p.FProcedure := AProcedure;
  p.FMethod := nil;
  p.Queued := true;
  LockList;
  try
    FSyncRecList.Add(p);
    Check;
  finally
    UnlockList;
  end;
end;

procedure TElegantThread.Synchronize(AMethod: TThreadMethod; ADebugInfo: string);
var
  p: PSyncRec;
  o: TSuperEvent;
begin

  // 此过程为阻塞执行,即调用者必须等到此过程被执行完成才能返回

  new(p);

  p.FProcedure := nil;
  p.FMethod := AMethod;
  p.Queued := false;
  p.FSignal := TSuperEvent.Create; // 创建一个信号
  p.FSignal.ResetEvent; // 清除信号
  o := p.FSignal;

  LockList;
  try
    FSyncRecList.Add(p);
    Check;
  finally
    UnlockList;
  end;

  o.WaitFor; // 等待信号出现
  o.Free;

end;

procedure TElegantThread.Synchronize(AProcedure: TThreadProcedure; ADebugInfo: string);
var
  p: PSyncRec;
  o: TSuperEvent;
begin
  new(p);

  p.FProcedure := AProcedure;
  p.FMethod := nil;
  p.Queued := false;
  p.FSignal := TSuperEvent.Create;
  p.FSignal.ResetEvent;
  o := p.FSignal;

  LockList;
  try
    FSyncRecList.Add(p);
    Check;
  finally
    UnlockList;
  end;

  o.WaitFor;
  o.Free;

end;

procedure TElegantThread.UnlockList;
begin
  FSyncRecList.Unlock;
end;

end.

uElegantThread.pas

 

附:delphi 进阶基础技能说明

http://www.cnblogs.com/lackey/p/4782777.html


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
delphi数组定义发布时间:2022-07-18
下一篇:
DELPHI7调用BERLIN中间件的中文字段名乱码的解决办法发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap