个人技术分享

[简介]
常用网名: 猪头三
出生日期: 1981.XX.XX
QQ: 643439947
个人网站: 80x86汇编小站 https://www.x86asm.org
编程生涯: 2001年~至今[共22年]
职业生涯: 20年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

[序言]
主要是记录TThreadedQueue的经典使用方式, 注意细节:
1> TThreadedQueue 内置同步机制
2> PopItem() 方法支持同步等待, 如果队列内容为空, 那么就会等待PushItem()放入元素
3> 如果TThreadedQueue<T>, 是对Integer类型进行泛型处理, 那么如果调用function PopItem(var AItem: T): TWaitResult; overload;的话, 会出现编译错误, 解决方式, 可以调用function PopItem(var AQueueSize: Integer; var AItem: T): TWaitResult; overload;进行绕过编译器错误.

[下面是经典代码]

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes, System.Generics.Collections,
  System.SyncObjs, System.Threading,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Bn_ReadThread: TButton;
    Memo_Result: TMemo;
    Bn_WriteThread: TButton;
    procedure Bn_ReadThreadClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Bn_WriteThreadClick(Sender: TObject);
  private
    { Private declarations }

    mpr_ShareQueue : TThreadedQueue<string> ;

    mpr_Threads_Count : Integer ;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  mpr_ShareQueue    := TThreadedQueue<string>.Create() ;
  mpr_Threads_Count := 0 ;
end;



procedure TForm1.FormShow(Sender: TObject);
begin
  Randomize() ;
  Memo_Result.Lines.Clear();
  Bn_WriteThread.Caption := Format('2: 创建写入线程(%d)', [mpr_Threads_Count]) ;
end;


// 单个读者线程
procedure TForm1.Bn_ReadThreadClick(Sender: TObject);
begin

  TTask.Run(procedure
  var
    str_Data : string ;
  begin

    // 循环读取
    while True do
    begin

      // 从线程同步队列中, 获取数据, 如果队列没有数据, 则会自动进入等待状态.
      if mpr_ShareQueue.PopItem(str_Data) = wrSignaled then
      begin

        // 获取到数据之后, 同步在界面上显式.
        TThread.Synchronize(TThread.Current, procedure
        begin
          Memo_Result.Lines.Add(str_Data) ;
        end);

      end
      else
      begin

        TThread.Synchronize(TThread.Current, procedure
        begin
          Memo_Result.Lines.Add('读取队列, 异常...') ;
        end);

      end;

    end;

  end);

end;// End Bn_ReadThreadClick()



// 多个写者线程(通过单击按钮, 反复创建多个写者线程)
procedure TForm1.Bn_WriteThreadClick(Sender: TObject);
var
  str_Data : string ;
begin

  Inc(mpr_Threads_Count) ;
  str_Data := Format('%d 号线程的数据.', [mpr_Threads_Count]) ;
  Bn_WriteThread.Caption := Format('2: 创建写入线程(%d)', [mpr_Threads_Count]) ;

  TTask.Run(procedure
  begin

    // 随机休眠时间
    TThread.Sleep((Random(5)+1)*1000) ;

    // 向线程同步队列添加数据.
    mpr_ShareQueue.PushItem(str_Data) ;

  end);

end;// End Bn_WriteThreadClick()


end.

[运行演示效果]