1,593
社区成员
发帖
与我相关
我的任务
分享
unit TestUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Generics.Collections,
System.SyncObjs, Vcl.StdCtrls;
type
TTestForm = class(TForm)
mmo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMissionQueue = class
strict private
const
DEFAULT_QUEUE_LENGTH = 100;
private
FQueue: TQueue<string>;
FCri: TCriticalSection;
FSem: THandle;
public
constructor Create(queueLength: Cardinal = DEFAULT_QUEUE_LENGTH);
destructor Destroy; override;
procedure Push(const filename: string);
function Pop(const timeout: Cardinal = INFINITE): string;
end;
TWorker = class(TThread)
protected
procedure Execute(); override;
end;
var
TestForm: TTestForm;
mq: TMissionQueue;
implementation
{$R *.dfm}
constructor TMissionQueue.Create(queueLength: Cardinal);
begin
FQueue := TQueue<string>.Create;
FCri := TCriticalSection.Create;
FSem := CreateSemaphore(nil, 0, queueLength, nil);
end;
destructor TMissionQueue.Destroy;
begin
CloseHandle(FSem);
FCri.Free;
FQueue.Free;
end;
function TMissionQueue.Pop(const timeout: Cardinal): string;
begin
Result := '';
case WaitForSingleObject(FSem, timeout) of
WAIT_OBJECT_0:
begin
FCri.Enter;
try
Result := FQueue.Dequeue;
finally
FCri.Leave;
end;
end;
end;
end;
procedure TMissionQueue.Push(const filename: string);
begin
FCri.Enter;
try
FQueue.Enqueue(filename);
finally
FCri.Leave;
end;
ReleaseSemaphore(FSem, 1, nil);
end;
{ TWorker }
procedure TWorker.Execute;
var
f: string;
begin
while not Terminated do
begin
f := mq.Pop();
if f = '' then
Break;
Synchronize(
procedure()
begin
TestForm.mmo1.Lines.Add('tid:' + IntToStr(ThreadID) + ' processing ' + f)
end);
Sleep(Random(3000)); //模拟处理
Synchronize(
procedure()
begin
TestForm.mmo1.Lines.Add('tid:' + IntToStr(ThreadID) + ' processed ' + f)
end);
end;
end;
procedure TTestForm.FormCreate(Sender: TObject);
var
i: Integer;
begin
mq := TMissionQueue.Create;
for i := 1 to 50 do
begin
mq.Push('file' + IntToStr(i)); //模拟插入50个待处理的文件名
end;
for i := 0 to 2 do
begin
TWorker.Create(False); //创建3个工作线程
end;
end;
procedure TTestForm.FormDestroy(Sender: TObject);
begin
mq.Free;
end;
end.