delphi多线程编程2Word文档下载推荐.docx
《delphi多线程编程2Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《delphi多线程编程2Word文档下载推荐.docx(20页珍藏版)》请在冰豆网上搜索。
EnterCriticalSection(CS);
{开始:
轮到我了其他线程走开}
LeaveCriticalSection(CS);
{结束:
其他线程可以来了}
DeleteCriticalSection(CS);
{删除:
注意不能过早删除}
//也可用TryEnterCriticalSection替代EnterCriticalSection.
用上临界区,重写上面的代码,运行效果图:
代码文件:
unitUnit1;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,StdCtrls;
type
TForm1=class(TForm)
ListBox1:
TListBox;
Button1:
TButton;
procedureFormCreate(Sender:
TObject);
procedureFormDestroy(Sender:
procedureButton1Click(Sender:
end;
var
Form1:
TForm1;
implementation
{$R*.dfm}
CS:
functionMyThreadFun(p:
Pointer):
DWORD;
stdcall;
i:
Integer;
begin
EnterCriticalSection(CS);
fori:
=0to99doForm1.ListBox1.Items.Add(IntToStr(i));
LeaveCriticalSection(CS);
Result:
=0;
end;
procedureTForm1.Button1Click(Sender:
ID:
CreateThread(nil,0,@MyThreadFun,nil,0,ID);
procedureTForm1.FormCreate(Sender:
ListBox1.Align:
=alLeft;
InitializeCriticalSection(CS);
procedureTForm1.FormDestroy(Sender:
DeleteCriticalSection(CS);
end.
Delphi在SyncObjs单元给封装了一个TCriticalSection类,用法差不多,代码如下:
usesSyncObjs;
TCriticalSection;
CS.Enter;
CS.Leave;
CS:
=TCriticalSection.Create;
CS.Free;
多线程编程(9)-认识等待函数WaitForSingleObject。
一下子跳到等待函数WaitForSingleObject,是因为下面的Mutex、Semaphore、Event、WaitableTimer等同步手段都要使用这个函数;
不过等待函数可不止WaitForSingleObject它一个,但它最简单.
functionWaitForSingleObject(
hHandle:
THandle;
{要等待的对象句柄}
dwMilliseconds:
DWORD {等待的时间,单位是毫秒}
):
{返回值如下:
}
WAIT_OBJECT_0 {等着了,本例中是:
等的那个进程终于结束了}
WAIT_TIMEOUT {等过了点(你指定的时间),也没等着}
WAIT_ABANDONED{好不容易等着了,但人家还是不让咱执行;
这一般是互斥对象}
//WaitForSingleObject的第二个参数一般给常数值INFINITE,表示一直等下去,死等.
WaitForSingleObject等待什么?
在多线程里就是等待另一个线程的结束,快来执行自己的代码;
不过它可以等待的对象可不止线程;
这里先来一个等待另一个进程结束的例子,运行效果图:
hProcess:
{进程句柄}
{等待一个指定句柄的进程什么时候结束}
ifWaitForSingleObject(hProcess,INFINITE)=WAIT_OBJECT_0then
Form1.Text:
=Format('
进程%d已关闭'
[hProcess]);
{启动一个进程,并建立新线程等待它的结束}
pInfo:
TProcessInformation;
sInfo:
TStartupInfo;
Path:
array[0..MAX_PATH-1]ofChar;
ThreadID:
{先获取记事本的路径}
GetSystemDirectory(Path,MAX_PATH);
StrCat(Path,'
notepad.exe'
);
{用CreateProcess打开记事本并获取其进程句柄,然后建立线程监视}
FillChar(sInfo,SizeOf(sInfo),0);
ifCreateProcess(Path,nil,nil,nil,False,0,nil,nil,sInfo,pInfo)then
begin
hProcess:
=pInfo.hProcess;
{获取进程句柄}
Text:
进程%d已启动'
CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);
{建立线程监视}
窗体文件:
objectForm1:
TForm1
Left=0
Top=0
Caption='
Form1'
ClientHeight=124
ClientWidth=241
Color=clBtnFace
Font.Charset=DEFAULT_CHARSET
Font.Color=clWindowText
Font.Height=-11
Font.Name='
Tahoma'
Font.Style=[]
OldCreateOrder=False
PixelsPerInch=96
TextHeight=13
objectButton1:
TButton
Left=88
Top=56
Width=75
Height=25
Caption='
Button1'
TabOrder=0
OnClick=Button1Click
end
end
多线程编程(10)-多线程同步之Mutex(互斥对象)。
原理分析:
互斥对象是系统内核对象,各线程都可以拥有它,谁拥有谁就能执行;
执行完毕,用ReleaseMutex函数释放拥有权,以让其他等待的线程使用.
其他线程可用WaitForSingleObject函数排队等候(等候也可以理解为排队申请).
使用过程:
varhMutex:
{应该先声明一个全局的互斥句柄}
CreateMutex {建立一个互斥对象}
WaitForSingleObject {用等待函数排队等候}
ReleaseMutex {释放拥有权}
CloseHandle {最后释放互斥对象}
ReleaseMutex、CloseHandle的参数都是CreateMutex返回的句柄,关键是CreateMutex函数:
functionCreateMutex(
lpMutexAttributes:
PSecurityAttributes;
bInitialOwner:
BOOL;
{是否让创建者(此例中是主线程)拥有该互斥对象}
lpName:
PWideChar {可以给此互斥对象取个名字,如果不要名字可赋值为nil}
{
1、第一个参数前面说过.
2、第二个参数在这里一定要是False,如果让主线程拥有互斥,从理论上讲,得等程序退出后其他线程才有机会;
取值False时,第一个执行的线程将会最先拥有互斥对象,一旦拥有其他线程就得先等等.
3、第三个参数,如果给个名字,函数将从系统中寻找是否有重名的互斥对象,如果有则返回同名对象的存在的句柄;
如果赋值为nil将直接创建一个新的互斥对象;
下个例子将会有名字.}
本例效果图:
代码文件:
f:
{用这个变量协调一下各线程输出的位置}
hMutex:
{互斥对象的句柄}
i,y:
Inc(f);
y:
=20*f;
=0to50000do
ifWaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20,y,IntToStr(i));
Form1.Canvas.Unlock;
Sleep(0);
{稍稍耽搁一点,不然有时Canvas会协调不过来}
ReleaseMutex(hMutex);
end;
Repaint;
f:
CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);
hMutex:
=CreateMutex(nil,False,nil);
CloseHandle(hMutex);
窗体文件:
ClientHeight=140
ClientWidth=192
OnCreate=FormCreate
Left=109
Top=107
SyncObjs单元下有封装好的TMutex类,好像不如Api快,内部机制也稍有区别,但使用方法差不多:
MyMutex:
TMutex;
ifMyMutex.WaitFor(INFINITE)=wrSignaledthen
MyMutex.Release;
MyMutex:
=TMutex.Create(False);
MyMutex.Free;
多线程编程(11)-多线程同步之Mutex(互斥对象)[续]。
Mutex作为系统核心对象是可以跨进程的(临界区就不行),我们可以利用互斥对象禁止程序重复启动.
工作思路:
先用OpenMutex尝试打开一个自定义名称的Mutex对象,如果打开失败说明之前没有这个对象存在;
如果之前没有这个对象,马上用CreateMutex建立一个,此时的程序应该是第一次启动;
再重复启动时,那个OpenMutex就有结果了,然后强制退出.
最后在程序结束时用CloseHandle释放Mutex对象.
functionOpenMutex(
dwDesiredAccess:
{打开权限}
bInheritHandle:
{能否被当前程序创建的进程继承}
pName:
PWideChar {Mutex对象的名称}
{成功返回Mutex的句柄;
失败返回0}
注意,这里的CreateMutex函数应该有个名了,因为OpenMutex要用到;
另外,CreateMutex的第二个参数已经不重要了(也就是True和False都行),因为这里是用其名称来判断的.
程序可以这样写:
Windows,Messages,Sy