多线程总结 - 陆续整理

做项目再次涉及到多线程的操作,曾经分时段研究了下多线程,每隔一段时间研究,总会多一点新的感悟和理解。

整理下,后续随时总结记录吧

1. 先谈谈两个命令,引出TEvent

    Suspend 和 Resume 两个命令,一个是暂停,一个是恢复继续执行

    因为两个命令自XE开始被标识为 deprecated, 而且不符合多线程安全(看了下TEvent说明,大致是因为TEven更适合TThread中进行多线程安全的操控)

    所以在此引入TEvent控制TThread

//需要使用 TEvent,必须先 uses System.SyncObjs;
//官方函数说明
constructor Create(
    //Set the EventAttributes parameter to specify the access rights and inheritance capabilities of the new event object. Calling Create with EventAttributes set to nil (Delphi) or NULL (C++) creates an event object with a default set of security attributes. If the TEvent object is created to access an existing named event object, only the bInheritHandle field of EventAttributes is used, as the access rights were determined when the event object was created. 
    EventAttributes: PSecurityAttributes;    

    //Set ManualReset to specify whether the signal of the TEvent object can only be turned off by a call to the ResetEvent method, or whether it is automatically reset when a single waiting thread is released. When ManualReset is true, the TEvent signal stays set until the ResetEvent method turns it off. When ManualReset is false, the signal is automatically turned off when only a single thread waits on the signal and that thread is released. If the TEvent object is created to access an existing named event object, the ManualReset parameter is ignored. 
    ManualReset,                                

    //Set InitialState to indicate whether the TEvent object should be created with the signal set, or turned off. When InitialState is true, the TEvent object is created with the signal set. If the TEvent object is created to access an existing named event object, the InitialState parameter is ignored. 
    InitialState: Boolean;                      

    //Set Name to provide a name for a new event object or to specify an existing named event object. If no other thread or process will need to access the event object to wait for its signal, Name can be left blank. Name can be a string of up to 260 characters, not including the backslash character (\). If Name is used to specify an existing event object, the value must match the name of the existing event in a case-sensitive comparison. If Name matches the name of an existing semaphore, mutex, or file-mapping object, the TEvent object will be created with Handle set to 0 and all method calls will fail.  
    const Name: String;

    //Set UseCOMWait to True to ensure that when a thread is blocked and waiting for the object, any STA COM calls can be made back into this thread. 
    UseCOMWait: Boolean = False
); overload;

a. 我们先创建TEvent,

TEvent.Create(
    nil, //使用默认的继承对象
    true,//因为后续需要手工暂停线程,所以这边要设置手动复位信号
    false,//因为我们希望线程创建后不立刻执行,所以这边初始化状态 Siganl 设置为False
    ''    //一般只用于个线程中,则留空吧,不需要区分多 TEvent
)

b.线程中设置一个信号复位函数用于供外部主线程控制线程

procedure TTest.Start;
begin
    Event.SetEvent;
end;

c.线程中TThread.Execute中 TEvent 的控制体现

procedure TTest.Execute;
begin
    Event.WaitFor;        //线程耐心等线程进行 SetEvent 给初始化信号

    //获取信号后执行
    Event.ResetEvent;
    while not terminated do
    begin

        //--------------------------
        //线程不释放,在此处进行其他命令的执行
        .....
        //--------------------------
        
        //一直等待信号中
        Event.WaitFor;
        Event.ResetEvent;
    end;
end;

d.线程完毕后释放时,对TEvent进行处理

destructor TTest.Destroy; 
begin
    Event.Free;
    inherited;
end;

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

完整代码

unit XXX

interface

uses
    System.Classes, Sytem.SyncObjs;
Type
    TTest = class(TThread)
        ....
    private
        Event: TEvent;
        procedure Execute;
    public
        constructor Create; overload;
        destructor Destroy; override;
        procedure Start;                   //******用于外部控制线程的函数                                            
    end;

    TFrm_XXX = class(TForm)
        FTest: TTest;
        procedure Btn_StartOnClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestory(Sender: TObject);
    end;

var
    Frm_XXX: TFrm_XXX;

implementation

constructor TTest.Create;
begin
    inherited Create(true);
    Event := TEvent.Create(nil,true,false,'');
end;

destructor TTest.Destroy;
begin
    Event.Free;
    inherited;
end;

procedure TTest.Execute;
begin
    Event.WaitFor;
    Event.ResetEvent;
    While not Terminated do
    begin
        .....
        
        Event.WaitFor;
        Event.ResetEvent;
    end;
end;

procedure TTest.Start;
begin
    Event.SetEvent;
end;


procedure TFrm_XXX.Btn_StartOnClick(Sender: TObject);
begin
    //多线程开动
    FTest.Start;
end;

procedure TFrm_XXX.FormCreate(Sender: TObject);
begin
    FTest := TTest.Create;
    FTest.FreeOnTerminate := true;
    
    //此处完整的线程对接,还需要给线程一个Sync到主线程的函数用以同步线程空间相关数据的反馈
    //不过不在这边讨论
end;

procedure TFrm_XXX.FormDestory(Sender: TObject);
begin
    FTest.Terminate;
    FTest.Start;
end;

2. 留位 (线程结果同步到出现中中)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值