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

时间:2021-11-18 08:07:38

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

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

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

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来说,每一个进来的请求&lpar;request&rpar;都需要一个线程,直到该请求结束。

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

  3. python笔记9-多线程Threading之阻塞&lpar;join&rpar;和守护线程&lpar;setDaemon&rpar;

    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. Ansible-Tower快速入门-2&period;准备开始【翻译】

    准备开始 欢迎来到ansible tower! 首先,您可以按照下面的快速安装说明进行安装,详细的安装说明可以查看章节标题“安装和设置指南”,然后,你可以通过快速启动来快速开启和运行tower,或者设 ...

  2. ACdream1157 Segments(CDQ分治 &plus; 线段树)

    题目这么说的: 进行如下3种类型操作:1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]2)C i (1-base) 删除第i条增加的线段, ...

  3. 让IE9支持html5

    IE10以上才算是真正支持了html5 ,但仍然有些地方和别的浏览器不一致,比如要在js里移除一个html标签, 如果是IE,document.getElementById("a" ...

  4. birt 集成到现有的web应用中

     我们已经有了一个Javaweb应用,现在要实现对报表的集成 我的应用是这个样子的  说明: 1)  这里使用的是birt4.4版本的, 下载birt-runtime-4.4.zip(在官方下载),然 ...

  5. IDEA搭建SpringMVC&plus;Mybatis&plus;Mysql&plus;Maven框架

    相关环境 Intellij IDEA Ultimate Tomcat JDK MySql 5.6(win32/win64) Maven (可使用Intellij IDEA自带的) 搭建步骤 创建项目工 ...

  6. PHP 完整表单实例

    PHP - 在表单中确保输入值 在用户点击提交按钮后,为确保字段值是否输入正确,我们在HTML的input元素中插添加PHP脚本, 各字段名为: name, email, 和 website. 在评论 ...

  7. Burp插件开发——环境配置

    最近打算开发个Burp插件,从网上各种地找资料学习.第一步就应该是环境配置,请见下文. (其实最重要的前提是你已经安装了Burp,否则下面的所有内容都是无稽之谈了. https://pan.baidu ...

  8. Go 基准测试

        文章转载地址:https://www.flysnow.org/2017/05/21/go-in-action-go-benchmark-test.html 什么是基准测试?      基准测试 ...

  9. git post-receive

    1. 将 www 目录设为 777 2. 用git 用户 mkdir 并 git init 3. cat  id_rsa.pub >. authorkeys

  10. 时间函数应用 time

    表 1. C 时间函数 function 定义 含义 返回值 精度 time() time 函数获得从 1970 年 1 月 1 日 0 点到当前的秒数,存储在time_t结构之中. time_t 秒 ...