delphi与多线程

来源:互联网 发布:单身 知乎 编辑:程序博客网 时间:2024/05/22 08:14
delphi与多线程(收集中……)
2008-07-09 15:15

Delphi多线程编程中的技巧

(1)创建线程(http://www.cqzol.com/programming/615617.html)
MsgThread := TMsgThread.Create(False) ; //创建并执行线程
MsgThread := TMsgThread.Create(True) ; //创建线程后挂起
constructor Create(CreateSuspended: Boolean); 中的参数CreateSuspended表示创建后是否挂起线程。
(2)设置线程里没有设置循环执行的话,且设置FreeOnTerminate为True,则线程执行完后就会自己释放。
(3)在一个线程结束后,调用另一个事件的方法:
只要设置Onterminate:=某方法,这样在线程结束前自然会被调用,比如 :
procedure TSendShortMessageThread.Execute;
var
Bitmap: Tbitamp;
begin
Bimap:=Tbitmap.create(nil) ;
OnTerminate:=Threaddone;
end;

procedure Threaddone(sender: tobject);
begin
Bimap.Free; //在Destory之前会被调用
end;
(4)程序结束前安全的退出线程的方法:
if MsgThread <> nil then
begin
MsgThread.Terminate ;
MsgThread.WaitFor ;
end;
(5)判断当前线程的状态:
//以下资料来自大富翁论坛。
/判断线程是否释放
//返回值:0-已释放;1-正在运行;2-已终止但未释放;
//3-未建立或不存在
function TFrmMain.CheckThreadFreed(aThread: TThread): Byte;
var
i: DWord;
IsQuit: Boolean;
begin
if Assigned(aThread) then
begin
IsQuit := GetExitCodeThread(aThread.Handle, i);
if IsQuit then //If the function succeeds, the return value is nonzero.
//If the function fails, the return value is zero.
begin
if i = STILL_ACTIVE then //If the specified thread has not terminated,
//the termination status returned is STILL_ACTIVE.
Result := 1
else
Result := 2; //aThread未Free,因为Tthread.Destroy中有执行语句
end
else
Result := 0; //可以用GetLastError取得错误代码
end
else
Result := 3;
end;
(6)线程同步。
如果线程要调用VCL里面的内容(如:别的窗体中的控件),就需要将这个线程同步。线程同步表示交由主线程运行这段代码,各个线程都在主线程中分时间段运行。另外,要想避免多个线程同时执行同一段代码也需要将多线程同步。
临界区和互斥的作用类似,都是用来进行同步的,但它们间有以下一点差别:
临界区只能在进程内使用,也就是说只能是进程内的线程间的同步;而互斥则还可用在进程之间的;临界区所花消的时间很少,才10~15个时间片,而互斥需要400多个;临界区随着进程的终止而终止,而互斥,如果你不用closehandle()的话,在进程终止后仍然在系统内存在,也就是说它是系统全局对象;
同步的方法有:

(1)使用临界区对象。
临界区对象有两种:TRTLCriticalSection 和 CriticalSection。
 TRTLCriticalSection的用法

var
GlobalVariable:Double;

var
CriticalSection:TRTLCriticalSection;

procedure SetGlobalVariable(Value:Double);
begin
EnterCriticalSection(CriticalSection); //进入临界区
try
GlobalVariable:=Value;
finally
LeaveCriticalSection(CriticalSection); //离开临界区
end;
end;

initialization
InitializeCriticalSection(CriticalSection); //初始化
finalization
DeleteCriticalSection(CriticalSection); //删除
end.
 CriticalSection(重要区段)的用法:
var criticalsection: TCriticalsection;
创建:criticalsection := TCriticalsection.create;
使用:
criticalsection.enter;
try
...
finally
criticalsection.leave;
end;

(2)使用互斥
先在主线程中创建事件对象:
var
hMutex: THandle = 0;
...
hMutex := CreateMutex(nil, False, nil);

在线程的Execute方法中加入以下代码:
if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
//Do Something;
...
ReleaseMutex(hMutex);

最后记得要释放互斥对象:
CloseHandle(hMutex);

(3)使用信号量

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

type
TMyThread = class(TThread)
private

protected
procedure Execute; override;
public

constructor Create; virtual;
end;

var
Form1 : TForm1;
HSem : THandle = 0 ;
implementation

{$R *.dfm}

var
tick: Integer = 0;
procedure TMyThread.Execute;
var
WaitReturn : DWord ;
begin
WaitReturn := WaitForSingleObject(HSem,INFINITE) ;
Form1.Edit1.Text := IntToStr(tick);
Inc(tick);
Sleep(10);
ReleaseSemaphore(HSem, 1, Nil)
end;

constructor TMyThread.Create;
begin
inherited Create(False);
FreeOnTerminate := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
HSem := CreateSemaphore(Nil,1,1,Nil) ;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(HSem) ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
index: Integer;
begin
for index := 0 to 10 do
begin
TMyThread.Create;
end;
end;

end.
一般的同步对象使用Mutex对象,是因为Mutex有一个特别之处:当一个持有对象的线程DOWN掉的时候,mutex对象可以自动让其它等待这个对象的线程接受,而其它的内核对象则不具体这个功能。
之所要使用Semaphore则是因为Semaphore可以提供一个活动线程的上限,即lMaximumCount参数,这才是它的真正有用之处。

//-------------------------------------------------------------------------------------------------------------------

【eNet硅谷动力专稿】我们都知道当前的Windows操作系统是一个“多线程”操作系统。那么什么是线程呢?线程就是进程中的一个实体,它和进程一样能够独立的执行控制,由操作系统负责调度,其区别就在于线程没有独立的存储空间,而是与同属于一个进程的其他线程共享一个存储空间,这使得多线程之间的通信较进程简单,并且多线程的执行都是并发而且是相互独立的。为了运行所有这些线程,操作系统为每个独立线程安排一些CPU 时间,操作系统以轮转方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。

  CreatThread函数是用于创建一个线程,CreatThread函数原形及参数说明如下:

  HANDLE CreatThread(

   LPSECURITY_ATTRIBUTES lpThreadAttributes,

   DWORD dwStackSize,

   LPTHREAD_START_ROUTINE lpStartAddress,

   LPVOID lpParameter,

   DWORD dwCreationFlags,

   LPDWORD lpThreadld

   ),

  参数说明:

  pThreadAttributes 如果为NULL,该线程使用默认安全属性。如果希望所有子进程能够继承该线程对象的句柄,必须将他的bInheritHand成员初始化为True。

  dwStackSize 设定线程堆栈的地址空间。如果非0,函数将所有的存储器保留并分配给线的程堆栈。

  lpStartAddress 线程函数的地址。

  lpParameter 传递给线程函数的参数。

  dwCreationFlags 如果是0,线程创建后立即对它进行调度,如果是CREATE_SUSPENDED,系统对它进行初始化后暂停该线程的运行。

  lpThreadld 用来存放系统分配给新线程的ID。

  下面这段程序就介绍了我们在使用线程和没有使用线程二种情况下,运行程序之后该程序的反应。当点击Button1按钮时,则建立一个线程,这时候我们可以看到在应用程序进行位图移动的同时,可以对窗体的尺寸大小进行改变或移动窗体位置。当按下Button2按钮时,则不建立线程,我们会发现程序在位图没有完全移动完之前根本不能做其它任何事情,如果我们设置位图循环移动的话,那么感觉这个应用程序就像死掉一样!

  unit Unit1;

  interface

  uses

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

   Dialogs, StdCtrls, ExtCtrls;

  

  type

   TForm1 = class(TForm)

   Button1: TButton;

   Button2: TButton;

   procedure Button1Click(Sender: TObject);

   procedure Button2Click(Sender: TObject);

   private

   { Private declarations }

   public

   { Public declarations }

   end;

  var

   Form1: TForm1;

  

  implementation

  

  {$R *.dfm}

  function NewThread(P:pointer):Longint;stdcall;

  var

  newbmp: TBitmap;

  i,bmpheight,bmpwidth:integer;

  begin

  newbmp:= TBitmap.Create;

  newbmp.Width:=500;

  newbmp.Height:=200;

  bmpwidth:=500;

  bmpheight:=200;

  newbmp.LoadFromFile('图片.bmp');

  for i:=0 to bmpheight do

  begin

  form1.Canvas.CopyRect(Rect(0,bmpheight-i,bmpwidth,bmpheight),newbmp.Canvas,Rect(0,0,bmpwidth,i)); //通过CopyRect方法,使位图实现在 form1窗体上的视觉上移

  sleep(10);//停留时间

  end;

  newbmp.free;

  end;

  procedure TForm1.Button1Click(Sender: TObject);

  var

   CThread:Thandle;//声明了一个句柄

   Tid:DWord;

  begin

   Cthread:=CreateThread(nil,0,@NewThread,nil,0,Tid); //创建一个线程,同时调用线程函数

  end;

  procedure TForm1.Button2Click(Sender: TObject);

  begin

  NewThread(nil); //没有创建线程时,直接调用线程函数

  end;

  end.

  以上代码在Delphi7上运行通过。

原创粉丝点击