欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    delphi与多线程编程之多线程同步之 CriticalSection.pdf

    • 资源ID:70013218       资源大小:117.42KB        全文页数:8页
    • 资源格式: PDF        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    delphi与多线程编程之多线程同步之 CriticalSection.pdf

    function CreateThread(lpThreadAttributes:Pointer;dwStackSize:DWORD;lpStartAddress:TFNThreadStartRoutine;入口函数的指针lpParameter:Pointer;dwCreationFlags:DWORD;var lpThreadId:DWORD):THandle;stdcall;-到了入口函数了,学到这个地方,我查了一个入口函数的标准定义,这个函数的标准返回值应该 是DWORD,不过 这函 数在Delphi 的System 单元 定义 的是:TThreadFunc=function(Parameter:Pointer):Integer;我以后会尽量使用 DWORD 做入口函数的返回值.这个返回值有什么用呢?等线程退出后,我们用 GetExitCodeThread 函数获取的退出码就是这个返回值!如果线程没有退出,GetExitCodeThread 获取的退出码将是一个常量 STILL_ACTIVE(259);这样我们就可以通过退出码来判断线程是否已退出.还有一个问题:前面也提到过,线程函数不能是某个类的方法!假如我们非要线程去执行类中的一个方法能否实现呢?尽管可以用 Addr(类名.方法名)或 MethodAddress(published 区的方法名)获取类中方法的地址,但都不能当做线程的入口函数,原因可能是因为类中的方法的地址是在实例化为对象时动态分配的.后来换了个思路,其实很简单:在线程函数中再调用方法不就得了,估计 TThread 也应该是这样.下面的例子就尝试了用线程调用 TForm1 类中的方法,并测试了退出码的相关问题.本例效果图:-代码文件:-unit Unit1;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls;typeTForm1=class(TForm)Button1:TButton;Button2:TButton;procedureButton1Click(Sender:TObject);procedureButton2Click(Sender:TObject);privateprocedureFormProc;准备给线程使用的方法end;varForm1:TForm1;implementation$R*.dfmvarhThread:THandle;线程入口函数function MyThreadFun(p:Pointer):DWORD;stdcall;beginForm1.FormProc;调用 TForm1 类的方法Result:=99;这个返回值将成为线程的退出代码,99 是我随意给的数字end;TForm1 的方法,本例中是给线程的入口函数调用的procedureTForm1.FormProc;vari:Integer;beginfori:=0 to 200000 dobeginwith Form1.Canvas do beginLock;TextOut(10,10,IntToStr(i);Unlock;end;end;end;建立并执行线程procedureTForm1.Button1Click(Sender:TObject);varID:DWORD;beginhThread:=CreateThread(nil,0,MyThreadFun,nil,0,ID);end;获取线程的退出代码,并判断线程是否退出procedureTForm1.Button2Click(Sender:TObject);varExitCode:DWORD;beginGetExitCodeThread(hThread,ExitCode);ifhThread=0 thenbeginText:=线程还未启动;Exit;end;ifExitCode=STILL_ACTIVE thenText:=Format(线程退出代码是:%d,表示线程还未退出,ExitCode)elseText:=Format(线程已退出,退出代码是:%d,ExitCode);end;end.-窗体文件:-object Form1:TForm1Left=0Top=0Caption=Form1ClientHeight=84ClientWidth=376Color=clBtnFaceFont.Charset=DEFAULT_CHARSETFont.Color=clWindowTextFont.Height=-11Font.Name=TahomaFont.Style=OldCreateOrder=FalsePixelsPerInch=96TextHeight=13object Button1:TButtonLeft=183Top=32Width=75Height=25Caption=Button1TabOrder=0OnClick=Button1Clickendobject Button2:TButtonLeft=280Top=32Width=75Height=25Caption=Button2TabOrder=1OnClick=Button2Clickendendfunction CreateThread(lpThreadAttributes:Pointer;dwStackSize:DWORD;堆栈大小lpStartAddress:TFNThreadStartRoutine;lpParameter:Pointer;dwCreationFlags:DWORD;var lpThreadId:DWORD):THandle;stdcall;-CreateThread 的第二个参数是分配给线程的堆栈大小.这首先这可以让我们知道:每个线程都有自己独立的堆栈(也拥有自己的消息队列).什么是堆栈?其实堆是堆、栈是栈,有时栈也被叫做堆栈.它们都是进程中的内存区域,主要是存取方式不同(栈:先进后出;堆:先进先出);栈(或叫堆栈)适合存取临时而轻便的变量,主要用来储存局部变量;譬如 fori:=0 to 99do 中的i就只能存于栈中,你把一个全局的变量用于 for 循环计数是不可以的.现在我们知道了线程有自己的栈,并且在建立线程时可以分配栈的大小.前面所有的例子中,这个值都是 0,这表示使用系统默认的大小,默认和主线程栈的大小一样,如果不够用会自动增长;那主线程的栈有多大?这个值是可以设定的:Project-Options-Delphi Compiler-Linking(如图)-栈是私有的但堆是公用的,如果不同的线程都来使用一个全局变量有点乱套;为解决这个问题 Delphi 为我们提供了一个类似 var 的 ThreadVar 关键字,线程在使用ThreadVar 声明的全局变量时会在各自的栈中留一个副本,这样就解决了冲突.不过还是尽量使用局部变量,或者在继承 TThread 时使用类的成员变量,因为 ThreadVar 的效率不好,据说比局部变量能慢 10 倍.在下面的例子就测试了用 var 和 ThreadVar 定义变量的不同.使用 var 效果图:-使用 ThreadVar 效果图:-代码文件:-unit Unit1;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls;typeTForm1=class(TForm)Button1:TButton;procedureButton1Click(Sender:TObject);end;varForm1:TForm1;implementation$R*.dfm/var num:Integer;全局变量threadvar num:Integer;支持多线程的全局变量function MyThreadFun(p:Pointer):DWORD;stdcall;varpy:Integer;beginpy:=Integer(p);while True dobeginInc(num);with Form1.Canvas do beginLock;TextOut(20,py,IntToStr(num);Unlock;end;Sleep(1000);然线程挂起 1 秒钟再继续end;end;procedureTForm1.Button1Click(Sender:TObject);varID:DWORD;begin借入口函数的参数传递了一个坐标点中的Y值,以让各线程把结果输出在不同位置CreateThread(nil,0,MyThreadFun,Ptr(20),0,ID);CreateThread(nil,0,MyThreadFun,Ptr(40),0,ID);CreateThread(nil,0,MyThreadFun,Ptr(60),0,ID);end;end.-窗体文件:-object Form1:TForm1Left=0Top=0Caption=Form1ClientHeight=106ClientWidth=180Color=clBtnFaceFont.Charset=DEFAULT_CHARSETFont.Color=clWindowTextFont.Height=-11Font.Name=TahomaFont.Style=OldCreateOrder=FalsePixelsPerInch=96TextHeight=13object Button1:TButtonLeft=80Top=40Width=75Height=25Caption=Button1TabOrder=0OnClick=Button1Clickendend-function CreateThread(lpThreadAttributes:Pointer;安全设置dwStackSize:DWORD;lpStartAddress:TFNThreadStartRoutine;lpParameter:Pointer;dwCreationFlags:DWORD;var lpThreadId:DWORD):THandle;stdcall;-CreateThread 的第一个参数 lpThreadAttributes 是指向 TSecurityAttributes 结构的指针,一般都是置为 nil,这表示没有访问限制;该结构的定义是:-/TSecurityAttributes(又名:SECURITY_ATTRIBUTES、_SECURITY_ATTRIBUTES)_SECURITY_ATTRIBUTES=recordnLength:DWORD;结构大小lpSecurityDescriptor:Pointer;默认 nil;这是另一个结构 TSecurityDescriptor 的指针bInheritHandle:BOOL;默认 False,表示不可继承end;/TSecurityDescriptor(又名:SECURITY_DESCRIPTOR、_SECURITY_DESCRIPTOR)_SECURITY_DESCRIPTOR=recordRevision:Byte;Sbz1:Byte;Control:SECURITY_DESCRIPTOR_CONTROL;Owner:PSID;Group:PSID;Sacl:PACL;Dacl:PACL;end;-够复杂的,但我们在多线程编程时不需要去设置它们,大都是使用默认设置(也就是赋值为nil).我 觉 得 有 必 要 在 此 刻 了 解 的 是:建 立 系 统 内 核 对 象 时 一 般 都 有 这 个 属 性(TSecurityAttributes);在接下来多线程的课题中要使用一些内核对象,不如先盘点一下,到时碰到这个属性时给个nil即可,不必再费神.建立事件function CreateEvent(lpEventAttributes:PSecurityAttributes;!bManualReset:BOOL;bInitialState:BOOL;lpName:PWideChar):THandle;stdcall;建立互斥function CreateMutex(lpMutexAttributes:PSecurityAttributes;!bInitialOwner:BOOL;lpName:PWideChar):THandle;stdcall;建立信号function CreateSemaphore(lpSemaphoreAttributes:PSecurityAttributes;!lInitialCount:Longint;lMaximumCount:Longint;lpName:PWideChar):THandle;stdcall;建立等待计时器function CreateWaitableTimer(lpTimerAttributes:PSecurityAttributes;!bManualReset:BOOL;lpTimerName:PWideChar):THandle;stdcall;-上面的四个系统内核对象(事件、互斥、信号、计时器)都是线程同步的手段,从这也能看出处理线程同步的复杂性;不过这还不是全部,Windows Vista 开始又增加了 Conditionvariables(条件变量)、Slim Reader-Writer Locks(读写锁)等同步手段.不过最简单、最轻便(速度最快)的同步手段还是 CriticalSection(临界区),但它不属于系统内核对象,当然也就没有句柄、没有 TSecurityAttributes 这个安全属性,这也导致它不能跨进程使用;不过写多线程时一般不用跨进程啊,所以 CriticalSection 应该是最常用的同步手段.下次接上,开始学习多线程的同步了.-原文地址:http:/www.xm5.org/book/7/

    注意事项

    本文(delphi与多线程编程之多线程同步之 CriticalSection.pdf)为本站会员(qwe****56)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开