现在的位置: 首页 > 综合 > 正文

多线程学习 – Delphi and other

2014年01月30日 ⁄ 综合 ⁄ 共 3692字 ⁄ 字号 评论关闭

本文系原创,可以无条件转载、复制和传播,但请注明出处,并保留本版权声明。

出处:http://blog.csdn.net/shamork

作者:shamork shamork  [AT]  163.com([AT]
为@)

本文系原创,可以无条件转载、复制和传播,但请注明出处,并保留本版权声明。

 

看了很长时间的资料了,一直没敢用多线程,一方面感觉太复杂,牵扯的东西太多,不敢随便下手,另一方面也是自己还没理解透,尝试了几次不得要领。今天下班路上边骑车边想,终于有了点眉目。总结如下:

 

1.线程执行函数一般没有参数(目前只知道C#有个带object参数的)

2.一般的同步函数也没有参数,例如invoke、synchronize等

3.并不是所有线程相关的代码都要用临界区隔离,而是有可能被多个线程访问的才需要

4.由于整体封装的需要以及以上三个原因,一般将线程函数封装到类中,这样就可以实现线程的参数化,也能将线程包装起来,减少外部使用时的复杂度

实现方式如下图所示:

经过包装之后,呵呵,至少线程函数就有参数了,同步代码也类似实现就行了。不过略麻烦,因为没有参数,所以只能一个函数对应一个私有变量。

晚上想了下,同步代码也可以类似封装,而且也不复杂,由于只会被线程访问,因此简单的写个函数包装一下私有变量就行了。

下面是个列子,新建一个application,在Form中建立两个按钮,一个文本框,一个label,一个memo,按如下命名

memo1: TMemo;

btnCreate: TButton;//创建/停止按钮

edtCnt: TEdit;    //线程数

Label1: TLabel; //caption:个

btnClear: TButton;//清空memo

然后下面代码覆盖unit1,。

注意版本:Delphi7

结果如下:

 

 

unit Unit1;

interface

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

type
    TestThread = class(TThread)
    private
        { Private declarations }
	//内部变量,创建线程时保存参数,这些参数只对类内对象可见,所以很安全
        Cnt: Cardinal;
        FHandle: THandle;
        FintV: Int64;
        Findex: Integer;
    protected
        procedure Execute; override;
        procedure AddString;//同步调用代码
        procedure AddErrString;//同步调用代码
        procedure AddOKString;//同步调用代码
    public
        constructor Create(bSuspend: Boolean; index: Integer; intv: Int64 = 50);{参数进去了}

    end;

    TForm1 = class(TForm)
        memo1: TMemo;
        btnCreate: TButton;
        edtCnt: TEdit;
        Label1: TLabel;
        btnClear: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure btnClearClick(Sender: TObject);
        procedure btnCreateClick(Sender: TObject);
    private
        { Private declarations }
    public
        { Public declarations }
        sText: string;
        procedure EndThread;
    end;

var
    Form1: TForm1;
    thl: TList;

implementation
{$R *.dfm}
{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure TestThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TestThread }

constructor TestThread.Create(bSuspend: Boolean; index: Integer; intv: Int64 = 50);
begin
    FintV := intv;
    Findex := index;
    inherited Create(bSuspend);
end;

procedure TestThread.AddErrString;
begin
    Form1.memo1.Lines.add('创建waitable timer 失败!');
end;

//其实这个也可以包装的,例如
{procedure AddString(str:string);
begin
    sText:=str;
    Synchronize(addStr);//addStr里操作sTest私有变量的值
end;
}


procedure TestThread.AddOKString;//这里没参数,因此函数与不同的动作对应即可,但是这样就要多搞几个函数了
begin
    Form1.memo1.Lines.add('Index: ' + IntToStr(Findex) + ' Interval: ' + IntToStr(FintV) + ' ThreadID:' + inttostr(self.ThreadID) + '创建成功!');
end;

procedure TestThread.AddString;
begin
    Form1.memo1.Lines.add('Index: ' + IntToStr(Findex) + ' Interval: ' + IntToStr(FintV) + ' ThreadID: ' + inttostr(self.ThreadID) + ' Time: ' + IntToStr(Cnt));
end;

procedure TestThread.Execute;
var
    dt: Int64;
begin
    { Place thread code here }
    dt := 10;
    FHandle := CreateWaitableTimer(nil, False, nil);
    if FHandle < 1 then
    begin
        Synchronize(AddErrString);
    end
    else
        Synchronize(AddOKString);
    SetWaitableTimer(FHandle, dt, FintV, nil, nil, False);
    while (not Self.Terminated) and (WaitForSingleObject(FHandle, 1000) = WAIT_OBJECT_0) do
    begin
        Inc(Cnt);
        Synchronize(AddString);
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    thl := TList.Create;
end;

procedure TForm1.EndThread;
begin
    if thl.Count > 0 then
    begin
        while (thl.Count > 0) do
        begin
            TestThread(thl.Items[0]).Terminate;
            thl.Delete(0);
        end;
        memo1.Lines.Add('All Threads Teminated!');
    end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    EndThread;
end;

procedure TForm1.btnClearClick(Sender: TObject);
begin
    memo1.Clear;
end;

procedure TForm1.btnCreateClick(Sender: TObject);
var
    i, j, k: Integer;
begin
    if thl.Count > 0 then
    begin
        EndThread;
    end
    else
    begin
        j := StrToInt(Trim(edtCnt.Text));
        for i := 0 to j do
        begin
            k := 29 + i * 130;
            thl.Add(TestThread.Create(False, i, k));
            Sleep(23);
        end;
        memo1.Lines.Add('All Threads Create OK!');
    end;
    if thl.Count > 0 then
        btnCreate.Caption := '终止'
    else
        btnCreate.Caption := '创建';
end;

end.

 

 

抱歉!评论已关闭.