delphi多线程编程Word格式文档下载.docx

上传人:b****6 文档编号:8646838 上传时间:2023-05-12 格式:DOCX 页数:21 大小:24.63KB
下载 相关 举报
delphi多线程编程Word格式文档下载.docx_第1页
第1页 / 共21页
delphi多线程编程Word格式文档下载.docx_第2页
第2页 / 共21页
delphi多线程编程Word格式文档下载.docx_第3页
第3页 / 共21页
delphi多线程编程Word格式文档下载.docx_第4页
第4页 / 共21页
delphi多线程编程Word格式文档下载.docx_第5页
第5页 / 共21页
delphi多线程编程Word格式文档下载.docx_第6页
第6页 / 共21页
delphi多线程编程Word格式文档下载.docx_第7页
第7页 / 共21页
delphi多线程编程Word格式文档下载.docx_第8页
第8页 / 共21页
delphi多线程编程Word格式文档下载.docx_第9页
第9页 / 共21页
delphi多线程编程Word格式文档下载.docx_第10页
第10页 / 共21页
delphi多线程编程Word格式文档下载.docx_第11页
第11页 / 共21页
delphi多线程编程Word格式文档下载.docx_第12页
第12页 / 共21页
delphi多线程编程Word格式文档下载.docx_第13页
第13页 / 共21页
delphi多线程编程Word格式文档下载.docx_第14页
第14页 / 共21页
delphi多线程编程Word格式文档下载.docx_第15页
第15页 / 共21页
delphi多线程编程Word格式文档下载.docx_第16页
第16页 / 共21页
delphi多线程编程Word格式文档下载.docx_第17页
第17页 / 共21页
delphi多线程编程Word格式文档下载.docx_第18页
第18页 / 共21页
delphi多线程编程Word格式文档下载.docx_第19页
第19页 / 共21页
delphi多线程编程Word格式文档下载.docx_第20页
第20页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

delphi多线程编程Word格式文档下载.docx

《delphi多线程编程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《delphi多线程编程Word格式文档下载.docx(21页珍藏版)》请在冰点文库上搜索。

delphi多线程编程Word格式文档下载.docx

(例程:

Tst_Thread.dpr)

在一个Form上放3个按钮和一个Memo,然后加上下面这段。

var

Form1:

TForm1;

m:

integer;

{$R 

*.dfm}

function 

Func1(const 

n:

Integer):

Integer;

// 

定义一个耗时函数来运行

Result:

=Round(abs(Sin(Sqrt(n))));

i:

for 

:

to 

20000000 

do

inc(m,Func1(i));

//m全局变量

TForm1.Button1Click(Sender:

TObject);

TForm1.Button2Click(Sender:

MyThread:

TMyThead;

=0;

=TMyThead.Create(False);

TForm1.Button3Click(Sender:

Memo1.Lines.Add('

ok'

+inttostr(m));

end.

Button1Click后,Button3要过好几秒才能按下(嘿嘿,我的机子好,书上的例子i才200万,我加到2000万Button3才延迟几秒)。

Button2Click后,立刻可以按Button3,这就是线程的好处。

另外,我这里还没搞懂线程在哪安全free,所以干脆不free了。

注意:

当TThread的Create()被调用时,需要传递一个布尔型的参数CreateSuspended。

如果把这个参数设成False,那么当调用Create()后,Excute()会被自动地调用,也就是自动地执行线程代码。

如果该参数设为True,则需要运行TThread的Resume()来唤醒线程。

一般情况下,当你调用Create()后,还会有一些其他的属性要求设置。

所以,应当把CreateSuspended参数设为True,因为在TThread已执行的情况下设置TThread的属性可能会引起麻烦。

再深入一点讲,在构造函数Create()中隐含调用了一个RTL例程BeginThread(),而它又调用了一个API函数CreateThread()来创建一个线程对象的实例。

CreateSuspended参数表明是否传递CREATE_SUSPEDED标志给CreateThread()。

三、线程的安全Free:

(ps:

这是我从PDF上copy整理的,例子稍微改过,本人没有那么高深)

当线程对象的Excute()执行完毕,我们就认为此线程终止了。

这时,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread()。

由ExitThread()来清除线程所占用的栈。

当结束使用TThread对象时,应该确保已经把这个ObjectPascal对象从内存中清除了。

这才能确保所有内存占有都释放掉。

尽管在进程终止时会自动清除所有的线程对象,但及时清除已不再用的对象,可以使内存的使用效率提高。

利用将FreeOnTerminate的属性设为True的方法来及时清除线程对象是最方便的办法,这只需要在Excute()退出前设置就行了。

设置方法如下:

FreeOnTerminate:

=True;

这样,当一个线程终止时,就会触发OnTerminate事件,就有机会在事件处理过程内清除线程对象了。

若提前退出,Excute()就要不断检查Terminated属性的值。

上面的代码继续加上:

//终止后自动free

=0to 

if 

Terminated 

then 

Break;

某些紧急情况下,你可以使用Win32API函数TerminateThread()来终止一个线程。

但是,除非没有别的办法了,否则不要用它。

例如,当线程代码陷入死循环时。

TerminateThread()的声明如下:

functionTerminateThread(hThread:

THandle;

dwExitCode:

DWORD);

TThread的Handle属性可以作为第一个参数,因此,TerminateThread()常这样调用:

TerminateThread(MyThread.Handle,0)

如果选择使用这个函数,应该考虑到它的负面影响。

首先,此函数在WindowsNT与在

Windows95/98下并不相同。

在Windows95/98下,这个函数能够自动清除线程所占用的栈;

而在WindowsNT下,在进程被终止前栈仍然保留。

其次,无论线程代码中是否有try...finally块,这个函数都会使线程立即停止执行。

这意味着,被线程打开的文件没有被关闭、由线程申请的内存没有被释放等情况。

而且,这个函数在终止线程的时候也不通知DLL,当DLL关闭时,这也容易出现问题。

四、线程的挂起和唤醒:

当线程Create()中的CreateSuspended属性为True时,线程创建后并不立即执行。

可以用用Suspend()和Resume()来动态地挂起或唤醒。

//挂起和唤醒

Func2(MyThread:

Memo:

TMemo);

PassTime:

Cardinal;

MyThread.Suspend;

=GetTickCount;

Memo.Lines.Add('

'

Sleep(2000);

//等待2秒

=GetTickCount-PassTime;

SuspendTime:

+inttostr(PassTime)+'

*m:

MyThread.Resume;

ReSumeTime:

TForm1.Button5Click(Sender:

Func2(MyThread,Memo1);

运行结果:

Memo1

2000*m:

9630399

五、取得线程的时间:

(本节只是介绍GetThreadTimes()的用法,可略过)

上例可以看见,用Windows.GetTickCount()来取得线程运行时间是不准确的。

Win32提供了一个API函数GetThreadTimes(),定义如下:

BOOLWINAPIGetThreadTimes(

HANDLEhThread,

LPFILETIMElpCreationTime,线程创建的时间

LPFILETIMElpExitTime,线程退出的时间。

如果线程还在执行,此值无意义。

LPFILETIMElpKernelTime,执行操作系统代码所用的时间。

LPFILETIMElpUserTime执行应用程序本身代码所用的时间。

);

函数返回值失败时为0,成功为不等于零的数。

可用GetLastError()来取得更详细的资料。

以上四个参数都是TFileTime类型。

此类型在Windows单元中声明如下:

typedefstruct_FILETIME{

DWORDdwLowDateTime;

DWORDdwHighDateTime;

}64位数,以100纳秒(1纳秒=10亿分之一秒)的时间间隔自1601年1月1号(UTC)表示。

TFileTime的长度是64位,为了进行数学运算可以把它转换为Int64。

例如两个TFileTime的值比较大小:

IfInt64(UserTime)>

Int64(KernelTime)thenBeep;

Delphi只提供了FileTimeToDosDateTime,FileTimeToLocalFileTime和FileTimeToSystemTime这三个转换函数,所以要自己写和TdateTime的转换函数。

上面的例子加多一个函数:

Func3(MyThread:

//计算线程时间

FileTimeToDateTime(FileTime:

TFileTime):

TDateTime;

//TFileTime转化成TDateTime

SysTime:

TSystemTime;

not 

FileTimeToSystemTime(FileTime,SysTime) 

then

Raise 

Exception.CreateFmt('

FileTimeToSystemTime 

failed.'

+

Error 

code 

%d'

[GetLastError]);

with 

SysTime 

=EncodeDate(wYear,wMonth,wDay)+

EncodeTime(wHour,wMinute,wSecond,wMilliseconds);

CreateTime,ExitTime,KernelTime,UserTime:

TFileTime;

GetThreadTimes(MyThread.Handle,CreateTime,ExitTime,KernelTime,UserTime) 

创建时间:

+DateTimeToStr(FileTimeToDateTime(CreateTime)));

退出时间:

+DateTimeToStr(FileTimeToDateTime(ExitTime)));

Win时间:

+DateTimeToStr(FileTimeToDateTime(KernelTime)));

进程时间:

+DateTimeToStr(FileTimeToDateTime(UserTime)));

---------------'

Func3(MyThread,Memo1);

9585649

---------------

2008-10-1019:

59:

31

1601-1-1

1601-1-223:

58

还是不清楚如何具体运用。

◆delphi多线程编程之二◆

Delphi2007+WinXPsp3例程:

Tst_Thread2.dpr)

一、线程的局部变量threadvar

type

TForm1 

class(TForm)

Button1:

TButton;

Memo1:

TMemo;

Button1Click(Sender:

public

Public 

TMyThread=class(TThread)

FNewStr:

string;

constructor 

Create(const 

ANewStr:

string);

threadvar

GlobalStr:

SetShowStr(const 

S:

s='

//MessageBox(0,pchar(GlobalStr),'

The 

String 

is...'

MB_OK)

inc(n);

Memo.Lines.Add(inttostr(n)+GlobalStr);

end 

else 

=S;

TMyThread.Create(const 

=ANewStr;

Inherited 

Create(False);

TMyThread.Execute;

SetShowStr(FnewStr, 

Form1.Memo1);

SetShowStr('

 

=1;

Hello 

World'

//Global:

='

//show 

1Global

TMyThread.Create('

Mygodsos'

show 

2Global

Sleep(100);

3Global 

end.

当GlobalStr声明不同时,结果分别是:

Threadvarvar

1HelloWorld1HelloWorld

3HelloWorld3Mygodsos

2Mygodsos2Mygodsos

Delphi利用关键字threadvar封装API线程局部存储。

它能使你在第一个运行的线程中创建一个全局变量的拷贝。

如果用ThreadVar声明变量,则在程序结束前必须手动释放其占用的空间(这个手动释放的问题不知道d2007解决没有?

(ps我看到很多关于threadvar释放要:

='

的,若不是string类型的给如何释放?

二、双线程看看Threadvar:

把Execute()里Create(False)改成Create(True)

MyThread1:

TMyThread;

MyThread2:

Form1.Memo1);

Global

=TMyThread.Create('

thread 

1:

2:

MyThread1.Resume;

MyThread2.Resume;

当GlobalStr声明为不同,结果对比是:

ThreadvarVar

4HelloWorld4thread2:

2thread1:

3thread2:

3thread2:

2thread1:

这里出现一个十分有趣的问题,若sleep()位置不同,结果不一样。

//Sleep(100);

改成这样后,结果是:

3HelloWorld3thread1:

4thread2:

4thread2:

留意一下前面的序号,似乎sleep()的作用比较奇怪。

三、Sleep()函数

Win32API过程Sleep()。

此过程声明如下:

procedureSleep(dwMilliseconds:

stdcall;

Sleep()过程用来告诉操作系统,当前的线程在参数dwMilliseconds指定的时间内不需要分配任何CPU时间。

插入这个调用是使很多的任务在发生时,使执行哪个线程有一些随机性。

通常,可以把参数dwMilliseconds设为0。

尽管,这并没有使当前的线程真的“睡眠”,但它使操作系统把CPU时间分给了其他优先级相等或更高的线程。

要小心Sleep()神秘的时间调整问题。

Sleep()可能会使你的机器出现特别的问题。

这种问题在另一台机器上可能无法再现。

对上面的例子,改回以下,把global设成var声明:

执行几次,结果:

看来sleep后,在主进程中先返回哪个线程是有一定的随机性的。

但前面的序号还是一样的,意思是虽然主进程返回哪个线程的次序不一样,但线程执行的次序还是没变。

不知道我这样理解对不对。

◆Delphi多线程编程之三同步读写全局数据◆

Tst_Thread3.dpr)

开始研究最重要的多线程读写全局数据了,结合书上的例子,我修改成下面的情况:

Tst_Thread3U;

uses

Windows, 

Messages, 

SysUtils, 

Variants, 

Classes, 

Graphics, 

Controls, 

Forms,Dialogs, 

StdCtrls;

cl

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2