在Delphi中利用线程--解决程序没有计算完之前不能做其它任何事情

a15963254 2011-06-02 03:45:40
新手可以借鉴

《〈在Delphi 中利用线程》的文章中, 其基本思想就是直接调用Windows API 的CreateThread 函数来创建一个线程。那么, 利用Delphi 自身所定义的丰富的标准例程库和数量更多、内容更广泛的( 非) 可视类库进行处理, 以取代直接调用Windows API 函数可否实现呢?回答是肯定的, 而且更有效、更保险:
---- 方法一: 利用RTL 库的System 单元中定义的一个标准例程BeginThread。此例程完整封装了Win32 的CreateThread 函数, 是一个带有异常处理的标准Pascal 函数, 几乎可以处理所有自身的异常, 相对于使用Win32 的CreateThread 函数, 其安全系数大大增强。
---- BeginThread 函数在创建时, 不是如CreateThread 函数仅仅完成两项任务: 创建一个线程; 创建一个能作为线程入口的函数。还增加了几项保护措施:
---- 把System 单元中声明的全局变量IsMultiThread 设为TRUE, 这样Delphi 的堆栈管理器就知道当前有多个线程在运行, 从而防止多个线程同时修改它的内部结构;
---- 另外, 在调用BeginThread 函数时, 可创建一个异常框架, 允许系统缺省的异常处理句柄捕获任何未有被处理的异常线程。如果在线程函数中有任何未被处理的异常, 会自动产生一个退出代码, 或者线程返回的句柄为0, 表示线程没有创建成功, 则应用程序将会调用EndThread 过程(Procedure EndThread(ExitCiode:Integer)), 自动终止线程的运行。
---- 其完整声明如下:
function BeginThread( SecurityAttributes: Pointer;
StackSize: Integer;
ThreadFunc: TThreadFunc;
Parameter: Pointer;
CreationFlags: Integer;
var ThreadId: Integer): Integer;
---- 各参数的使用特点类似CreateThread 函数:
---- SecurityAttributes 参数是一个指向SECURITY_ATTRIBUTES 结构的指针, 其目的用于设置线程的访问权限,nil 表示为默认的安全属性。
---- StackSize 参数用于设置分配给线程的栈空间大小,0 表示用默认值。
---- ThreadFunc 用于指定一个函数, 该函数在线程创建后开始执行代码时调用。
---- Parameter 参数传递给ThreadFunc 参数所指定的函数, 常为nil, 或者设为一个32 位的指针, 指向一个数据结构。
---- CreationFlags 参数用于指定线程创建后是不是立即执行,0 表示立即执行,CREATE_SUSPENDED 表示处于挂起状态。
---- ThreadId 参数表示为每个线程唯一的识别号, 当BeginThread 函数返回后, 此参数就是线程的识别号。
---- 返回值为该线程的句柄, 如果为0, 表示表示线程没有创建成功, 可以调用Windows 的GetLastError 函数分析错误的原因。
---- 方法二: 利用Delphi 的VCL 库中TThread 对象。Delphi 的一个缺陷是不支持多个线程同时访问它的VCL 库, 但Delphi 的设计者们并没有刻意掩饰这个缺陷, 而是专门创建了一个TThread 对象以解决这个问题。这个TThread 对象封装了Windows API 和System 单元中有关线程运用的多个函数和例程, 利用操作系统分时段给各线程方式控制各个线程的“休眠”与“唤醒”以达到线程工作的同步, 当被“唤醒”后就调用TThread 对象的Synchronize 过程通知主线程, 让主线程去真正地访问VCL, 使得在一个应用程序中同时访问多个VCL 库成为了可能, 当然, 对于进行一般的多线程编程, 就更加简单了。
---- 在使用上它与Delphi 中大多数对象不同的是TThread 类是一个带有虚拟抽象对象方法的类, 我们不能直接创建TThread 对象的实例, 而必须先声明一个以TThread 对象为基类的类, 再用这个派生类创建实例和操纵线程具体的类属性和方法。具体声明可参看其源代码(c:\program files\borland\delphi 3\source\vcl\classes.pas) 或其它参考书。
---- 结合上述两种方法给出一例子程序, 以显示利用Delphi 自身强大的处理功能如何建立及使用线程, 创建一个Form 窗体,Caption 设为“线程创建例子程序”, 在窗体中放入四个TButton 控件, 分别设置Caption“例程创建成功”、“例程创建失败”和“类创建成功”、“类创建失败”。Name 分别为“routines1Button”、“routines2Button”和“class1button”、“class2button”, 一个TEedit 控件,text 设置为“”:
unit threadsimple;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
class1button: TButton;
class2button: TButton;
routines1Button: TButton;
routines2Button: TButton;
procedure class1buttonClick(Sender: TObject);
procedure routines1ButtonClick(Sender: TObject);
procedure routines2ButtonClick(Sender: TObject);
procedure class2buttonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
tmythread=class(tthread)
count:integer;
myedit:tedit;
procedure show;virtual;abstract;
constructor create(myedit1:tedit);
end;
thread1=class(tmythread)
procedure show; override;
procedure execute;override;
end;
thread2=class(tmythread)
procedure show; override;
procedure execute;override;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure mythreadfunc;// 创建的线程函数
var
i:integer;
dc:hdc;
s:string;
begin
for i:=0 to 100000 do
begin
s:=inttostr(i);
dc:=getdc(form1.edit1.handle);
textout(dc,0,0,pchar(s),length(s));
releasedc(form1.edit1.handle,dc);
end;
end;
constructor tmythread.create(myedit1:tedit);// 创建线程
begin
inherited create(false);
myedit:=myedit1;
freeonterminate:=true; // 线程终止时自动删除对象,
end;
procedure thread1.show;// 类调用的线程函数
begin
myedit.Text:=inttostr(count);
end;
procedure thread1.execute; // 线程方法重载
var
i:integer;
begin
for i:=0 to 100000 do
begin
count:=i;
synchronize(show); // 线程调用同步
end;
end;
procedure thread2.show;// 类调用的线程函数
begin
mythreadfunc;
end;
procedure thread2.execute; // 线程方法重载
begin
synchronize(show); // 线程调用同步
end;
procedure TForm1.class1buttonClick(Sender: TObject);// 引用类方法创
建线程
begin
with thread1.create(edit1) do
end;
procedure TForm1.class2buttonClick(Sender: TObject);
// 引用类方法创
建线程
begin
with thread2.create(edit1) do
end;
procedure TForm1.routines1ButtonClick(Sender: TObject);
// 引用例程创建线程
var
hthread:thandle;
thid:dword;
begin
hthread:=beginthread(nil,0,@mythreadfunc,nil,0,thid);
if hthread=0 then
showmessage(' 创建线程失败');
end;
procedure TForm1.routines2ButtonClick(Sender: TObject);
// 用例程创建线程失败
begin
mythreadfunc;
end;
end.
---- 点击“成功”按钮, 该应用程序成功的创建了一个线程, 在Edit1 框内不断计算数据的同时, 改变窗体的大小或移动窗体均能实现。而在点击“失败”按钮后, 会发现此应用程序中只能有一个主线程存在, 在程序没有计算完之前根本不能做其它任何事情!
...全文
149 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
dropme 2011-06-02
  • 打赏
  • 举报
回复
哦,帮顶,蹭分~
a15963254 2011-06-02
  • 打赏
  • 举报
回复
procedure TForm1.routines2ButtonClick(Sender: TObject);
// 用例程创建线程失败
begin
mythreadfunc;
end;

你这个明明是在主线程里做事,这是哪门子的“创建线程”...
上面是回复的这个问题
a15963254 2011-06-02
  • 打赏
  • 举报
回复
[Quote=引用楼主 a15963254 的回复:]
新手可以借鉴

《〈在Delphi 中利用线程》的文章中, 其基本思想就是直接调用Windows API 的CreateThread 函数来创建一个线程。那么, 利用Delphi 自身所定义的丰富的标准例程库和数量更多、内容更广泛的( 非) 可视类库进行处理, 以取代直接调用Windows API 函数可否实现呢?回答是肯定的, 而且更有效、更保险:
---- 方法一: 利用RTL ……
[/Quote]

这里是测试他的反面效果,使例程创建线程失败程序在运算期间不能做任何操作。
yqdragon 2011-06-02
  • 打赏
  • 举报
回复
不是问问题是吧?
专制的网站 2011-06-02
  • 打赏
  • 举报
回复
什么和什么啊?? 散分?那我接分了...


procedure TForm1.routines2ButtonClick(Sender: TObject);
// 用例程创建线程失败
begin
mythreadfunc;
end;

你这个明明是在主线程里做事,这是哪门子的“创建线程”...
DELPHI专题文档-程序应用 更改Windows95的墙纸 类似于VB的doevents功能 DELPHI下的多线程程序设计 用Delphi 3.0编制MP3音乐点歌台 用Delphi开发windows95屏幕保护预览程序 判断一个程序是否dos版本 Delphi自定义消息应用一例 显示密码编辑框的密码 也谈Delphi的日期输入 用修改文件时间的方法来加密文件 在DELPHI处理时间 在Delphi用拼音首字符序列来实现检索功能 用Delphi创建Internet快捷方式 用Delphi实现远程屏幕抓取 资源文件在DELPHI的使用 在DELPHI应用程序使用DLL 为DELPHI应用程序制作安装程序 用注册表对Delphi程序进行加密 在Delphi程序操作注册表 鼠标和键盘控制 如何为Delphi程序添加事件和事件处理器 在Delphi应用程序拖动控件 用DEPHI为应用软件建立注册机制 用Delphi创建临时文件 Delphi 5快速创建控制面板程序 Delphi经验技巧集锦 Microsoft Agent技术在Delphi的应用 怎样建立简单的任务栏应用程序 判断一个程序是否dos版本 利用Delphi 5调用Excel 97 利用Dll实现通用密码验证框 如何访问一个进程的内存空间 用Delphi 5.0编写OLE程序操纵Excel 用Delphi编写DLL实现动态改变分辨率 在delphi使用flash控件 在Delphi运用QuickReport实现多栏列印 控制INI文件几法 转让控制权 得到执行程序的目录 打开已注册文件 得到Windows用户名和序列号 关闭外部应用程序 查阅可视窗口标题 在Delphi编程创建一个启动闪现窗口 如何用Delphi编ScreenSaver Delphi里如何计算日期 delphi怎样调用外部EXE文件 Win95/98下监控运行的其他程序 控制面板应用大全 避免一个程序二次运行 转换WINDOWS壁纸 改计算机名 为应用程序添加口令 启动屏幕保护 控制热启动 辨别显示分辨率 获得WINDOWS的临时路径 状态条插入可视控件 统计英文字个数 获得Windows类型和版本 读INI文件 大小写金额转换 检测程序是否运行 用Delphi3编写"共享软件" 如何从任务栏上隐藏应用程序的按纽 如何在Delphi程序支持文件拖放 如何运行一个程序直到它结束 用De1phi编制汉字录入能力测试软件 一个实用的Delphi屏幕拷贝程序的设计 如何一个SYSTRAY程序 查阅可视窗口标题 屏蔽系统功能键 状态条插入可视控件 如何隐藏和显示Windows的任务条 如何将你的程序放在Windows启动 获取当前程序的目录
DELPHI专题文档-程序应用 更改Windows95的墙纸 类似于VB的doevents功能 DELPHI下的多线程程序设计 用Delphi 3.0编制MP3音乐点歌台 用Delphi开发windows95屏幕保护预览程序 判断一个程序是否dos版本 Delphi自定义消息应用一例 显示密码编辑框的密码 也谈Delphi的日期输入 用修改文件时间的方法来加密文件 在DELPHI处理时间 在Delphi用拼音首字符序列来实现检索功能 用Delphi创建Internet快捷方式 用Delphi实现远程屏幕抓取 资源文件在DELPHI的使用 在DELPHI应用程序使用DLL 为DELPHI应用程序制作安装程序 用注册表对Delphi程序进行加密 在Delphi程序操作注册表 鼠标和键盘控制 如何为Delphi程序添加事件和事件处理器 在Delphi应用程序拖动控件 用DEPHI为应用软件建立注册机制 用Delphi创建临时文件 Delphi 5快速创建控制面板程序 Delphi经验技巧集锦 Microsoft Agent技术在Delphi的应用 怎样建立简单的任务栏应用程序 判断一个程序是否dos版本 利用Delphi 5调用Excel 97 利用Dll实现通用密码验证框 如何访问一个进程的内存空间 用Delphi 5.0编写OLE程序操纵Excel 用Delphi编写DLL实现动态改变分辨率 在delphi使用flash控件 在Delphi运用QuickReport实现多栏列印 控制INI文件几法 转让控制权 得到执行程序的目录 打开已注册文件 得到Windows用户名和序列号 关闭外部应用程序 查阅可视窗口标题 在Delphi编程创建一个启动闪现窗口 如何用Delphi编ScreenSaver Delphi里如何计算日期 delphi怎样调用外部EXE文件 Win95/98下监控运行的其他程序 控制面板应用大全 避免一个程序二次运行 转换WINDOWS壁纸 改计算机名 为应用程序添加口令 启动屏幕保护 控制热启动 辨别显示分辨率 获得WINDOWS的临时路径 状态条插入可视控件 统计英文字个数 获得Windows类型和版本 读INI文件 大小写金额转换 检测程序是否运行 用Delphi3编写"共享软件" 如何从任务栏上隐藏应用程序的按纽 如何在Delphi程序支持文件拖放 如何运行一个程序直到它结束 用De1phi编制汉字录入能力测试软件 一个实用的Delphi屏幕拷贝程序的设计 如何一个SYSTRAY程序 查阅可视窗口标题 屏蔽系统功能键 状态条插入可视控件 如何隐藏和显示Windows的任务条 如何将你的程序放在Windows启动 获取当前程序的目录
Delphi7编程100例》代码目录:---------------------------------------------ToolBar工具栏控件的使用动态建立主菜单选项窗口界面的动态分隔条动态设置选项卡页面在标题栏自定义按钮窗体开合窗帘效果Windows XP界面效果实现OutLook滚动工具栏效果在下拉列表框显示树形视图自定义系统的About项修改系统级菜单实现透明窗体效果爆破特技窗体只允许建立一次子窗体的MDI程序从外部DLL调用子窗口新颖的资源管理器界面如何生成半圆形窗口制作字幕滚动窗体详解Canvas生成渐变色窗口背景WINAPM风格磁化窗口软件封面的图片显示制作实现图片的任意角度旋转奇妙的拼图游戏使用PaintBox控件制作画图程序使用DrawGrid控件制作五子棋多彩的数据报表按压缩比将BMP转换为JPG16位真彩转换到256色调整图片的RGB对比度实现图像的灰度级处理效果3种像素历遍方法的比较和实现实现屏幕拷贝实现图像漫游4种幕布式图像显示技巧盘旋法实现9种滤镜效果图形朦胧叠合显示技巧给MDI主窗体增加背景实现图像的淡入淡出显示多媒体播放器播放AVI文件根据客户端IP地址获取计算机名实现多线程IP和DomainName相互转换Windows2000下的Popup发送功能如何实现Ping操作实现多线程共享探测实现Windows95/98的I/O端口读写收发电子邮件与监视网络服务器资源使用WebBrower制作浏览器可视化的Ping工具使用IdMappedPortTCP进行端口映射动态设置ODBC数据源用ADO控件打开Access数据库DBGrid的记录到Html页面的转换在DBGrid实现任意方向查找在DBGrid通过动态下拉列表查找记录用DBGrid组件制作下拉列表形式的提示框利用书签处理DBGrid的多个记录将ComboBox的内容直接拖放到DBGrid里如何在DBGrid里放置图标DBGrid控件精彩组合DBChart图表控件的使用在StringGrid组件显示查询结果使用流对象(Tstream)实现数据表Tmemo字段的显示如何动态建立SQLServer ODBCSQL浏览器在SQL查询使用动态参数事务工作原理标准/模糊查询筛选数据数据字典查看器TDecisionGraph决策组件的使用明细表(Master/Detail)结构像处理文本资料一样处理数据表的信息远程数据库登录远程数据库的离线处理在远程数据库实现主从表关系动态设置远程数据库的查询参数在远程数据库计算统计值多线程与数据库使用远程存储过程数据模块的同步显示建立Web服务的数据提供端建立Web服务的数据访问端开发WebSnap数据库程序建立ActiveForm数据浏览建立数据查询WebServices服务器端数据查询Web服务客户端开发基于WAP的手机无线应用建立基本Web数据库服务器应用建立类型库编辑DataSnap服务端建立查询条件Web数据库服务器应用建立基本MTS服务端建立MTS数据访问客户端建立IntraWeb数据浏览将程序图标设置到Windows系统托盘取得和修改文件的创建和修改日期通过流式数据实现文件分割与合并实现指定扩展名文件和相应程序的关联获取汉字拼音的首字母监视剪贴板在IE工具栏上增加一个按钮图标软件注册机制的建立复活节彩蛋的制作SkinEngine控件——XP换肤ActionList——应用程序通用功能列表OleContainer——OLE容器将程序项设置到控制面板艺术化排列桌面图标Delphi的ini文件的读写建立键盘鼠标动作记录与回放实现指定目录下的文件查询实现对系统的操作监视系统级热键的实现检测NumLock、Insert、CapsLock、ScrollLock键的状态
目录: 1 Uppas40.htm Delphi 4增訂的Object Pascal 19K 2 Api_printer.htm Api函数列表-与打印有关 30K 3 Autocreate.htm 在Delphi3程序自动检测、建立数据库别名 7K 4 Autoxize.htm DELPHI自适应表单的实现 3K 5 Bat.htm 在Delphi利用Tbatch组件成数据批处理 5K 6 Bde.htm 如何在注册表注册BDE 2K 7 Bjjlb.htm Delphi编辑俱乐部 4K 8 Cgi_1.htm CGI技术及其开发 11K 9 Cgi_2.htm CGI技术及其开发(二) 12K 10 Chang_backmap.htm 用Delphi实现壁纸更换 3K 11 Change_ip_dns.htm 任何动态改变/添加网络设置的 TCP/IP 的 DNS 地址 1K 12 Colorcour.htm 让彩色光标出现在Delphi程序 2K 13 Compon_mk.htm 面向组件的系统开发方法 2K 14 Comtech.htm COM/DCOM如何传递数组 2K 15 Comvsdcom.htm COM/DCOM的区别与联系 2K 16 Cookite.htm Delphi 3Cookie的建立使用 6K 17 Copy_screen.htm 一个实用的Delphi屏幕拷贝程序的设计 11K 18 Create_oracle7.htm 开发基于ORACLE7数据库的管理信息系统 9K 19 Cs_fast.htm 提高客户机/服务器应用系统性能的一些方法 8K 20 Def_color_dlg.htm 用Delphi实现自定义颜色对话框及其构件 12K 21 Def_preview.htm 自定义快速报表的打印预览窗口 6K 22 Delete.htm 如何把文件删除到回收站 1K 23 Delphi_c.htm 在Delphi与C++之间实现函数与对象共享 7K 24 Delphi_err.htm Delphi编译错误文手册 34K 25 Delphi_net1.htm DELPHI与INTERNET 34K 26 Delphi_net2.htm DELPHI与INTERNET 46K 27 Delphi_quick_develop.htm Delphi之快速设计(程序设计篇) 8K 28 Delphi_quick_develop2.htm Delphi之快速设计(界面篇) 3K 29 Delphi23_io.htm 在DELPHI2.0/3.0直接操作端口 3K 30 Delphivspb.htm 开发AS/400应用系统PB5与Delphi3的比较 9K 31 Device_isok.htm 检查驱动器是否就绪 1K 32 Dtccw03.htm 资源文件在DELPHI的使用 10K 33 Dttray.htm 如何创建任务栏的应用程序 11K 34 Edit_sysmenu.htm 控制系统菜单 3K 35 Fix_sybase.htm 如何恢复Sybase SQL Anywhere的数据库 4K 36 Fixsysbase_in.htm 解决sybase用户数据库不能进入故障的一种方法 5K 37 From_move.htm 用Delphi实现无边界窗体的移动 3K 38 Function.htm 部分函数、命令、属性文说明 13K 39 Get_form.htm Win95/98下监控运行的其他程序 2K 40 Get_info.htm 使用Delphi获取系列信息 3K 41 Get_net_friend.htm 如何在程序动态取得Win95/98的网络邻居的工作组及计算机名 12K 42 H_sort.htm 在DELPHI线程排序 4K 43 Happymouse.htm 用Delphi编制趣味动画鼠标 3K 44 Hint.htm 改造HINT的输出方式 5K 45 Howto_chinese_delphi.htm "Delphi全汉语"终结版 6K 46 If.htm Delphi数据集过滤技巧 4K 47 Img.htm Delphi下汉字输入法的编程及使用 5K 48 Index_notf.htm 怎样解决打开一个DBF表时的"Index not found.."错误 3K 49 Install.htm 如何制作Delphi程序安装盘 7K 50 Ip

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧