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

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

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

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. codecomb 2100【警察叔叔就是这个人!】

    题目背景 十个地方十人十色 全部都是猥琐大叔 这里也是那里也是 行踪可疑 现如今hentai横行,警察叔叔们不得不采取特♂殊手段惩戒这些家伙 题目描述 魅力之都是一个有N个路口,M条双向道路连接的城市 ...

  2. easyui 表单验证validatetype——支持自定义验证

    easyui 的validatebox()提供了自定义验证的方法,为此我把一些常用的数据验证汇总了一下,代码如下: 代码 Code highlighting produced by Actipro C ...

  3. Light OJ 1067 Combinations (乘法逆元)

    Description Given n different objects, you want to take k of them. How many ways to can do it? For e ...

  4. PHP 表单验证 - 完成表单实例

    ------------------------------------------------------------------------------------------- 本节展示如何在用 ...

  5. Unity 制作RPG地图2(自己控制地图上图标)

    上一次用Unity摄像机方式实现了地图的制作,现在介绍另一种实现地图的方式: 自己通过代码实现小地图NCP图标的显示和隐藏 制作地图的步骤: 1. 根据游戏人物的3D坐标转换成2D平面坐标,根据距离显 ...

  6. Ajax——ajax调用数据总结

    在做人事系统加入批量改动的功能中,须要将前台中的数据传给后台.后台并运行一系列的操作. 通过查询和学习了解到能够通过ajax将值传入到后台,并在后台对数据进行操作. 说的简单点.就是ajax调用后台的 ...

  7. [AC自动机][HDU3065]

    //====================== // HDU 2222 // 求目标串中出现了几个模式串 //输入 //1 //5 //she //he //say //shr //her //ya ...

  8. 【二分查找+优化O(n)】【续UVA1121】Subsequence

    之前的二分答案做法 http://blog.csdn.net/zy691357966/article/details/40212215 二分查找做法: 我们首先试试只枚举终点.对于终点j,我们的目标是 ...

  9. android一些常用的代码1(收藏)

    以下内容来自多个开源项目的整理和自己的项目积累. 1.拨打电话 public static void call(Context context, String phoneNumber) { conte ...

  10. Android通过PHP连接MySQL(用到Json)

    1下载phpnow 如果已经有mysql 则需要换一个端口 在服务器机器上的phpnow安装目录E:\PHPnow-1.5.5\htdocs下新建一个test.php文件: 其中我用的数据库是test ...