canvas教程

fd详细教程|Excel_VBA_详细教程(9)

字号+ 作者:H5之家 来源:H5之家 2017-05-02 18:01 我要评论( )

不过最简单、最轻便(速度最快)的同步手段还是 CriticalSection(临界区), 但它不属于系统内核对象, 当然也就没有句柄、没有 TSecurityAttributes 这个安全属性, 这也导致它不能跨进程使用; 不过写多线程时一般不用跨

不过最简单、最轻便(速度最快)的同步手段还是 CriticalSection(临界区), 但它不属于系统内核对象, 当然也就没有句柄、没有 TSecurityAttributes 这个安全属性, 这也导致它不能跨进程使用; 不过写多线程时一般不用跨进程, 所以 CriticalSection 应该是最常用的同步手段.

delphi多线程 delphi线程详细教程简单到复杂

二、临界区。(]

先看一段程序, 代码文件:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

ListBox1: TListBox;

Button1: TButton;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

function MyThreadFun(p: Pointer): DWORD; stdcall;

var

delphi多线程 delphi线程详细教程简单到复杂

i: Integer;

begin

for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i)); Result := 0;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

ID: DWORD;

begin

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

ListBox1.Align := alLeft;

end;

end.

delphi多线程 delphi线程详细教程简单到复杂

在这段程序中, 有三个线程几乎是同时建立, 向窗体中的 ListBox1 中写数据, 最后写出的结果是这样的:

能不能让它们别打架, 一个完了另一个再来? 这就要用到多线程的同步技术.

前面说过, 最简单的同步手段就是 "临界区".

先说这个 "同步"(Synchronize), 首先这个名字起的不好, 我们好像需要的是 "异步"; 其实异步也不准确...

管它叫什么名字呢, 它的目的就是保证不冲突、有次序、都发生.

"临界区"(CriticalSection): 当把一段代码放入一个临界区, 线程执行到临界区时就独占了, 让其他也要执行此代码的线程先等等; 这和前面用的 Lock 和 UnLock 差不多; 使用格式如下:

var CS: TRTLCriticalSection; {声明一个 TRTLCriticalSection 结构类型变量; 它应该是全局的}

InitializeCriticalSection(CS); {初始化}

EnterCriticalSection(CS); {开始: 轮到我了其他线程走开}

LeaveCriticalSection(CS); {结束: 其他线程可以来了}

DeleteCriticalSection(CS); {删除: 注意不能过早删除}

//也可用 TryEnterCriticalSection 替代 EnterCriticalSection.

delphi多线程 delphi线程详细教程简单到复杂

用上临界区, 重写上面的代码, 运行效果图:

//用临界区重写后的代码文件:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

ListBox1: TListBox;

Button1: TButton;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure Button1Click(Sender: TObject);

end;

delphi多线程 delphi线程详细教程简单到复杂

var

Form1: TForm1;

implementation

{$R *.dfm}

var

CS: TRTLCriticalSection;

function MyThreadFun(p: Pointer): DWORD; stdcall;

var

i: Integer;

begin

EnterCriticalSection(CS);

for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i)); LeaveCriticalSection(CS);

Result := 0;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

ID: DWORD;

begin

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

end;

delphi多线程 delphi线程详细教程简单到复杂

procedure TForm1.FormCreate(Sender: TObject);

begin

ListBox1.Align := alLeft;

InitializeCriticalSection(CS);

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

DeleteCriticalSection(CS);

end;

end.

Delphi 在 SyncObjs 单元给封装了一个 TCriticalSection 类, 用法差不多, 代码如下: unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

ListBox1: TListBox;

Button1: TButton;

procedure FormCreate(Sender: TObject);

delphi多线程 delphi线程详细教程简单到复杂

procedure FormDestroy(Sender: TObject);

procedure Button1Click(Sender: TObject);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

uses SyncObjs;

var

CS: TCriticalSection;

function MyThreadFun(p: Pointer): DWORD; stdcall;

var

i: Integer;

begin

CS.Enter;

for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i)); CS.Leave;

Result := 0;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

delphi多线程 delphi线程详细教程简单到复杂

ID: DWORD;

begin

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

ListBox1.Align := alLeft;

CS := TCriticalSection.Create;

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

CS.Free;

end;

end.

三、等待函数 WaitForSingleObject

一下子跳到等待函数 WaitForSingleObject, 是因为下面的 Mutex、Semaphore、Event、WaitableTimer 等同步手段都要使用这个函数; 不过等待函数可不止 WaitForSingleObject 它一个, 但它最简单.

function WaitForSingleObject(

hHandle: THandle; {要等待的对象句柄}

dwMilliseconds: DWORD {等待的时间, 单位是毫秒}

): DWORD; stdcall; {返回值如下:}

delphi多线程 delphi线程详细教程简单到复杂

WAIT_OBJECT_0 {等着了, 本例中是: 等的那个进程终于结束了} WAIT_TIMEOUT {等过了点(你指定的时间), 也没等着}

WAIT_ABANDONED {好不容易等着了, 但人家还是不让咱执行; 这一般是互斥对象}

//WaitForSingleObject 的第二个参数一般给常数值 INFINITE, 表示一直等下去, 死等.

WaitForSingleObject 等待什么? 在多线程里就是等待另一个线程的结束, 快来执行自己的代码; 不过它可以等待的对象可不止线程; 这里先来一个等待另一个进程结束的例子, 运行效果图:

//WaitForSingleObject的示例代码文件:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

delphi多线程 delphi线程详细教程简单到复杂

type

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

var

hProcess: THandle; {进程句柄}

{等待一个指定句柄的进程什么时候结束}

function MyThreadFun(p: Pointer): DWORD; stdcall;

begin

if WaitForSingleObject(hProcess, INFINITE) = WAIT_OBJECT_0 then Form1.Text := Format('进程 %d 已关闭', [hProcess]);

Result := 0;

end;

{启动一个进程, 并建立新线程等待它的结束}

procedure TForm1.Button1Click(Sender: TObject);

var

pInfo: TProcessInformation;

delphi多线程 delphi线程详细教程简单到复杂

sInfo: TStartupInfo;

Path: array[0..MAX_PATH-1] of Char;

ThreadID: DWORD;

begin

{先获取记事本的路径}

GetSystemDirectory(Path, MAX_PATH);

StrCat(Path, '\notepad.exe');

{用 CreateProcess 打开记事本并获取其进程句柄, 然后建立线程监视} FillChar(sInfo, SizeOf(sInfo), 0);

if CreateProcess(Path, nil, nil, nil, False, 0, nil, nil, sInfo, pInfo) then

begin

hProcess := pInfo.hProcess; {获取进程句柄}

Text := Format('进程 %d 已启动', [hProcess]);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID); {建立线程监视}

end;

end;

end.

四 、 垂钓大青鱼,详细教程

青鱼

【形态特征】

青鱼体较大,长筒形,尾部稍侧扁。(]头顶宽平。

【栖息场所】

多栖息在水体的中下层,一般不游至水面

【咬口状况】

除冬季食欲较弱外,春、夏、秋三季摄食猛烈,且能在气压较低、大多数底栖鱼类普遍厌食的情况下咬钩吞饵

【溜鱼方法】

1、变换站位,或人随鱼沿岸而走

2、改变牵引方向,借臂力使竿呈侧向弯弓后与之周旋

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • delphi开发经验技巧...

    delphi开发经验技巧...

    2016-12-24 14:02

网友点评