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

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

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

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 + ##;
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

delphi 把多个线程的请求阻塞到另一个线程 TElegantThread的更多相关文章

  1. java的服务是每收到一个请求就新开一个线程来处理吗?tomcat呢?

    首先,服务器的实现不止有这两种方式. 先谈谈题主说的这两种服务器模型: 1.收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会 ...

  2. 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。

    这段时间折腾了哈java web应用的压力测试,部署容器是tomcat 7.期间学到了蛮多散碎的知识点,及时梳理总结,构建良好且易理解的知识架构把它们组织起来,以备忘.对web应用开发者来说,我们很关 ...

  3. python笔记9-多线程Threading之阻塞(join)和守护线程(setDaemon)

    python笔记9-多线程Threading之阻塞(join)和守护线程(setDaemon) 前言 今天小编YOYO请xiaoming和xiaowang吃火锅,吃完火锅的时候会有以下三种场景: - ...

  4. 开启两个线程,一个线程打印A~Z,一个线程打印1~52的数据

    开启两个线程,一个线程打印A-Z,一个线程打印1-52的数据 import java.util.concurrent.locks.Condition; import java.util.concurr ...

  5. 死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  6. 死磕 java线程系列之自己动手写一个线程池(续)

    (手机横屏看源码更方便) 问题 (1)自己动手写的线程池如何支持带返回值的任务呢? (2)如果任务执行的过程中抛出异常了该怎么处理呢? 简介 上一章我们自己动手写了一个线程池,但是它是不支持带返回值的 ...

  7. 两个线程,一个线程打印1~52,另一个线程打印字母A-Z,打印顺序为12A34B56C……5152Z

    使用wait,notify实现 public class Test { public synchronized void a() { for (int i = 1; i <= 52; i++) ...

  8. Java线程唤醒与阻塞

    阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一 定已经很熟悉了.Java 提供了大量方法来支持阻塞,下面让我们逐一分析. 转载于:http://blog.cs ...

  9. jmeter 线程数—请求数详解

    一个性能测试请求负载是基于一个线程组完成的.一个测试计划必须有一个线程组.测试计划添加线程组非常简单.在测试计划右键弹出下拉菜单(添加-->Threads(Users)--->线程组)中选 ...

随机推荐

  1. C语言的本质(35)——共享库

    库用于将相似函数打包在一个单元中.然后这些单元就可为其他开发人员所共享,并因此有了模块化编程这种说法- 即,从模块中构建程序.Linux支持两种类型的库,每一种库都有各自的优缺点.静态库包含在编译时静 ...

  2. Kth Largest Element in an Array 解答

    Question Find the kth largest element in an unsorted array. Note that it is the kth largest element ...

  3. OpenWrt修改

    openwrt如何编译修改界面的顶部.底部信息.LOGO图片 2011-06-02 16:20:03  浏览次  以Atheros71xx为例,修改路径为:trunk/build_dir/target ...

  4. Struts2 学习笔记 10 Result部分 part1

    1.关于Result我们首先来学习一下结果类型 result type. 先来看struts.xml. struts.xml <?xml version="1.0" enco ...

  5. tr转换或删除字符

    字符处理命令:tr —— 转换或删除字符 逐个字符处理而不是处理单词的tr [OPTION]... SET1 [SET2]    -d: 删除出现在字符集中的所有字符 tr ab AB

  6. jQuery 局部div刷新和全局刷新方法

    div的局部刷新 $(".dl").load(location.href+".dl");  全页面的刷新方法 window.location.reload( ) ...

  7. Unity编辑器扩展Texture显示选择框

    学习NGUI插件的时候,突然间有一个问题为什么它这些属性可以通过弹出窗口来选中呢? 而我自己写的组件只能使用手动拖放的方式=.=. Unity开发了组件Inspector视图扩展API,如果我们要写插 ...

  8. 谋哥:研究App排行榜浮出的神器

    昨天发的<App排行榜的秘密>到头条网,阅读量到2万,踩的比顶的多几倍.原因是由于我使用360市场的数据来分析,而且这帮喷子根本不看你分析数据背后的意义,反正看到自己不喜欢的比方" ...

  9. javascript 命名空间,学习

    一. (function(){ var _NS=function(){ } _NS.prototype.alert=function(){ console.log('test'); } window. ...

  10. Sql Server相关的性能计数器

    OS Memory and Paging 性能计数器: 1.Memory\Availability Mbytes   未使用的物理内存(非页面文件),通常情况下它应该大于100MB 2.Memory\ ...