电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 在线教程-> ASP
WIN32下DELPHI中的多线程【变量存储】(三)-ASP教程,系统相关
作者:网友供稿 点击:28
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 

线程中的变量
    由于每个线程都代表了一个不同的执行路径,因此,最好有一种只限于一个线程内部使用的数据,
    要实现上述目的有以下几种方式:
    1、局部变量(基于栈),很简单,在你的线程函数中你定义的变量既是如此。由于每个线程都在各自的栈中,各个线程将都有一套局部变量的副本,这样,就不会相互影响。对于那些只在过程或函数的生存期有意义的变量,应当把它们声明为局部变量。
    2、存储在线程对象中。还记得createthread函数中的lpparameter参数吗,它可以接受一个无类型的指针。结合本文第一章的内容,你应该还记得,它被存储在线程内核对象的上下文结构中,你可以通过context结构中的context_integer部分的ebx来读取它的地址。
    下面是一段示例代码,用来演示读取context结构,这段代码一般用不到,但它可以说明cratethread函数中的lpparameter被存储的位置

{
    作者:wudi_1982
    联系方式:wudi_1982@hotmail.com
    转载请著名出处,本代码为演示代码,只贴出了一些关键部分
}


type
  
//传递给线程函数的结构和指针的声明
  tinfo = record
    count : integer;
    x : integer;
    y : integer;
  end;
  pinfo
= ^tinfo;

var
mythreadhad : thandle;
//一个全局变量,用来保存线程的句柄

//线程函数
function mythread(info : pointer):dword; stdcall;
var
  i : integer;
begin
  
//根据传递来信息决定在窗口的那个位置输出什么信息
  for i := 0 to pinfo(info)^.count-1 do
    form1.image1.canvas.textout(pinfo(info)
^.x,pinfo(info)^.y,inttostr(i));
  
//freemem(info);
  result := 0;
end;

//创建一个线程
procedure tform1.button4click(sender: tobject);
var
  ppi : pinfo;
  mythreadid : dword;
begin
  
//分配空间并赋初值
  ppi :=allocmem(sizeof(tinfo));
  ppi
^.count := 1000000;
  ppi
^.x := 10;
  ppi
^.y := 10;
  
//创建
  mythreadhad := createthread(nil,0,@mythread,ppi,create_suspended,mythreadid);
  
//在窗体上显示线程函数的地址和传递给它的参数的地址
  labthreadaddr.caption := inttostr( integer(@mythread));
  labthreadpvparam.caption :
= inttostr(integer(ppi));
end;

//读取context结构,注意context结构是和cpu有关的,我这里测试时,工作在intel的cpu上
procedure tform1.btnrcontextclick(sender: tobject);
var
  con : _context;
begin
  
//初始化结构
  con.contextflags := context_full;
  
//读取
  getthreadcontext(mythreadhad,con);
  
//显示在窗体的listbox上
  with lbxcontextinfo.items do
  begin
  
//  clear;
    add(------------context--------------);
    add(
);
    add(
context_debug_registers-----);
    add(
dr0:+#9+inttostr(con.dr0));
    add(
dr1:+#9+inttostr(con.dr1));
    add(
dr2:+#9+inttostr(con.dr2));
    add(
dr3:+#9+inttostr(con.dr3));
    add(
dr6:+#9+inttostr(con.dr6));
    add(
dr7:+#9+inttostr(con.dr7));
    add(
context_segments---------);
    add(
seggs:+#9+inttostr(con.seggs));
    add(
segfs:+#9+inttostr(con.segfs));
    add(
seges:+#9+inttostr(con.seges));
    add(
segds:+#9+inttostr(con.segds));
    add(
context_integer.---------);
    add(
edi: +#9+inttostr(con.edi));
    add(
esi: +#9+inttostr(con.esi));
    add(
ebx: +#9+inttostr(con.ebx));
    add(
edx: +#9+inttostr(con.edx));
    add(
ecx: +#9+inttostr(con.ecx));
    add(
eax: +#9+inttostr(con.eax));
    add(
context_control----------);
    add(
ebp: +#9+inttostr(con.ebp));
    add(
eip: +#9+inttostr(con.eip));
    add(
segcs: +#9+inttostr(con.segcs));
    add(
eflags: +#9+inttostr(con.eflags));
    add(
esp: +#9+inttostr(con.esp));
    add(
segss: +#9+inttostr(con.segss));
  end;

end;

       把上面代码整理之后,添加到你的程序中,你可以发现(如果也是intel的cpu),那么你可以从eax寄存器读取到线程函数的地址,从ebx中读取到传递给线程函数的参数地址。
    在delphi中的tthread对象的构造函数中,你可以看到这段代码
fhandle := beginthread(nil, 0, @threadproc, pointer(self), create_suspended, fthreadid);
再观察beginthread的实现,你会发现tthread的调用createthread时,将pointer(self),也就是tthread对象本身当作线程函数的参数传递过去,换言之,你在tthread的派生类中定义的变量,对于一个线程而言,将存储在这个线程单独的堆栈中,而它在堆栈的地址存储在线程的上下文结构中。
    可以做一个简单的试验,将一个线程生成多次,你可以发现存储在线程对象内部的变量将互不影响。
    说到这里,必须谈论一个问题,效率的问题,我在一本书上曾经看到过这样一段话“由于访问线程对象中的数据比访问线程局部变量要快10倍,因此,你应当尽可能地把线程专用的信息保存在线程对象中。”对此,我一直没有特别理解。如果一定要相信这句话,那我会这么理解,就是存储在线程对象中的变量因为上下文结构记录了它的地址等原因,所以它更快。尽信书不如无书,我还在思考,不过好在这种速度的影响对于通常的使用而言影响不大。

3、在delphi中,用object pascal的关键字threadvar来声明变量,以利用操作系统级的线程局部存储。
    在前面我们了解到:虽然对于局部变量,在每个线程中都一个副本,然而应用程序的全局变量是被所有线程所共享的。当多个线程对这个全局变量进行访问时,将可能出现很多未知的问题,win32提供了一种称为线程局部存储的方式,它能使你在第一个运行的线程中创建一个全局变量的拷贝。delphi利用关键字threadvar封装此功能。在threadvar关键字下你可以声明任何局部存储的变量。
4、全局变量,多线程最让人头疼的地方就是全局变量了,好的同步方式将决定你高效、安全的访问全局变量,虽然上述的threadvar是解决全局变量线程局部存储的一个办法,但在我实际的编码工作中,几乎很少用它,它的局限性太多。多线程访问全局变量的方法将在下一文中详细描述。 


文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·如何使XP的目录属性出现"安全"选项-ASP教程,系统相关
·创建有个性的对话框之MFC篇(二)-ASP教程,系统相关
·用InstallShield打包ASP程序-ASP教程,ASP应用
·windows server 2003 中 SQL Server 2000 分布式事务 错误解决方法-ASP教程,系统相关
·创建有个性的对话框之MFC篇(一)-ASP教程,系统相关
·DevExpress打印相关代码-ASP教程,打印相关
·File文件控件,选中文件(图片,flash,视频)即立即预览显示-ASP教程,组件开发
·用Windows的文件映射机制,实现大批量数据的快速存储-ASP教程,系统相关
·ADO如何取得数据库中表的字段信息之一
·使用DEVEXPRESS部件打印时标题的处理-ASP教程,打印相关

最新文章
· SQL注入天书 - ASP注入漏洞全接触
·用.net 处理xmlHttp发送异步请求
·asp.net创建文件夹的IO类的问题
·如何实现ASP.NET网站个性化
·关于ASP.NET调用JavaScript的实现
·ASP利用Google实现在线翻译功能
·Asp无组件生成缩略图
·由HTTP 500 Internal server error想到的...
·实例讲解asp抓取网上房产信息
·改mdb为asp所带来的灾难


 
 


版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号