zoukankan      html  css  js  c++  java
  • Delphi异步编程:匿名线程与匿名方法

    异步编程,是项目中非常有用的而且常用的一种方法,大多以线程实现。

    而Delphi传统方法使用线程略为烦琐,好在其后续版本中,提供一些方法,简化一些操作。

    几个概念:

    匿名线程:TAnonymousThread,Delphi XE始支持。

    匿名方法:reference to procedure|function,Delphi 2009 始支持。

    匿名线程

    其实只是创建一个线程,传入一匿名方法并执行,实现倒也简单,我就移其入Dephi 2009中。其实义如下:

      TAnonymousThread = class(TThread)
      private
        FProc: TProc;
      protected
        procedure Execute; override;
      public
        constructor Create(const AProc: TProc);
      end;
    { TAnonymousThread }
    
    constructor TAnonymousThread.Create(const AProc: TProc);
    begin
      inherited Create(True);
      FreeOnTerminate := True;
      FProc := AProc;
    end;
    
    procedure TAnonymousThread.Execute;
    begin
      FProc();
    end;

    这样,使用简单的多线程,就不必再继承TThread类创建自己线程去工作了。其参数TProc,即为一匿名方法。

    而在TThread类中,定义一类方法直接创建,其方法为:

        // CreateAnonymousThread will create an instance of an internally derived TThread that simply will call the
        // anonymous method of type TProc. This thread is created as suspended, so you should call the Start method
        // to make the thread run. The thread is also marked as FreeOnTerminate, so you should not touch the returned
        // instance after calling Start as it could have run and is then freed before another external calls or
        // operations on the instance are attempted.
        class function CreateAnonymousThread(const ThreadProc: TProc): TThread; static;
    class function TThread.CreateAnonymousThread(const ThreadProc: TProc): TThread;
    begin
      Result := TAnonymousThread.Create(ThreadProc);
    end;

    由此可见,一行代码即可实现简单的线程操作。

    匿名方法

    自定义匿名方法,正式语法为:

    type
      TFun = reference to function(const num: Integer): Integer;

    procedure也是一样。但在SysUtils单元中,已内置一些预定义类型并且支持泛型,可直接拿来用,如下所示:

    // Generic Anonymous method declarations
    type
      TProc = reference to procedure;
      TProc<T> = reference to procedure (Arg1: T);
      TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
      TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
      TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4);
    
      TFunc<TResult> = reference to function: TResult;
      TFunc<T,TResult> = reference to function (Arg1: T): TResult;
      TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult;
      TFunc<T1,T2,T3,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3): TResult;
      TFunc<T1,T2,T3,T4,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4): TResult;
    
      TPredicate<T> = reference to function (Arg1: T): Boolean;

    我是喜欢懒省事的,有已有的即不再自写,上面诸多类型,已能应对大多数使用场景了。

    需要注意的是TFunc使用方法,因为它有返回值。比如TFunc<Integer, Interger>就与TFun实现原理一样。

    可验证如下代码:

    procedure TfrmMain.FormCreate(Sender: TObject);
    var
      f1: TFun;
      f2: TFunc<Integer, string>;
    begin
      f1 := function (const num: Integer): Integer
      begin
        Result := num * num;
      end;
      OutputDebugString(PChar('f1(9) = ' + IntToStr(f1(9))));  //Debug output: f1(9) = 81
    
      f2 := function (num: Integer): string
      begin
        Result := IntToStr(num * num);
      end;
      OutputDebugString(PChar('f2(9) = ' + f2(9)));    //Debug output: f2(9) = 81
    end;

    由此可延伸开来,匿名线程与匿名方法结合,可简单的执行并行操作,举例如下:

    procedure TfrmMain.btnStartClick(Sender: TObject);
    begin
      Edit1.Text := 'start...';
      TThread.CreateAnonymousThread(
        procedure
        var
          i: Integer;
        begin
          Sleep(3000);
          for i := 0 to 99999 do
            TThread.Synchronize(nil,
              procedure
              begin
                Edit1.Text := IntToStr(i);
              end
            );
          Edit1.Text := 'end.';  //此处亦要同步,懒省事没整Synchornize
        end
      ).Start;
    end;

    创建一匿名线程,传以匿名方法,并同步主线程显示,工作正常。相比c#之{}来说,begin..end的确看起业不像话。

    多省事,是不是?

    参考资料:

    Anonymous Methods in Delphi

    现在, Delphi 的多线程已经非常易用了!

    Delphi 2009 中的匿名方法(reference to)

  • 相关阅读:
    boost::ASIO的异步方式
    C++ 类构造函数初始化列表
    C++11 shared_ptr(智能指针)详解
    C/C++中静态成员变量和静态成员函数的含义与不同用法
    静态局部变量
    GDB入门教程之如何使用GDB启动调试
    Qt的QWaitCondition了解一下吧
    Qt信号量QSemaphore认识一下
    瞧一瞧Qt的QMutex
    Qt的读写锁QReadWriteLock要怎么玩?
  • 原文地址:https://www.cnblogs.com/crwy/p/9510398.html
Copyright © 2011-2022 走看看