쓰레드 클래스를 생성하지 않고 함수 호출만으로 쓰레드를 사용하기 위한 유닛입니다. "RyuLib for Delphi" 소스는 아래의 링크에서 받으시기 바랍니다.
http://ryulib.tistory.com/notice/11
사용법은 [소스 1]과 같습니다.
[소스 1]
function InternalThreadFunction(lpThreadParameter: Pointer): Integer; stdcall;
begin
Result := 0;
// TOO :
end;
procedure TfmMain.btCalcClick(Sender: TObject);
begin
QueueWorkItem(InternalThreadFunction, nil);
end;
10: 새로운 함수를 쓰레드 풀에 넣어서 실행 시킬 수 있을 때 함수가 실행됩니다. 쓰레드 생성 등에 대한 오버 헤드가 없습니다.
1-6: 함수의 형태는 1-6: 라인과 같아야 합니다.
1: lpThreadParameter 인자는 쓰레드와 호출 객체가 서로 공유 할 데이터나 객체를 전달 받기 위한 것입니다. 필요없으면 사용하지 않아도 됩니다.
ThreadPool 유닛에는 [소스 2]와 같은 형태의 함수가 제공됩니다. 각각 필요한 작업에 따라 선택하시면 됩니다.
[소스 2]
function QueueWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
function QueueIOWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
function QueueUIWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
[소스 3]은 1부터 n까지 더하는 프로그램을 멀티 쓰레드로 작성해 본 것 입니다. 속도를 줄이기 위해서 중간에 Sleep(1)로 쉬도록 했습니다. [그림 1]은 실행 결과 화면이며, 1000 --> 100 --> 10 순으로 계산을 했지만, 멀티 쓰레드이다 보니 먼저 계산 된 것부터 표시되고 있습니다. 가장 처음 입력한 수는 좀 큰 수였는데, 한 참 동안 계산이 안끝나서 중간에 캡쳐된 것을 올립니다.
[그림 1] 실행 결과
[소스 3]
unit _fmMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Spin;
type
TfmMain = class(TForm)
btCalc: TButton;
ListBox1: TListBox;
SpinEdit1: TSpinEdit;
procedure btCalcClick(Sender: TObject);
private
procedure do_WM_User(var Msg:TMessage); message WM_User;
public
end;
var
fmMain: TfmMain;
implementation
uses
ThreadPool;
{$R *.dfm}
type
TContext = class
n : integer;
Handle : THandle;
end;
function InternalThreadFunction(lpThreadParameter: Pointer): Integer; stdcall;
var
Loop, Sum : integer;
Context : TContext absolute lpThreadParameter;
begin
Result := 0;
Sum := 0;
for Loop := 1 to Context.n do begin
Sum := Sum + Loop;
Sleep(1);
end;
PostMessage(Context.Handle, WM_User, Sum, Context.n);
end;
procedure TfmMain.btCalcClick(Sender: TObject);
var
Context : TContext;
begin
Context := TContext.Create;
try
Context.n := SpinEdit1.Value;
Context.Handle := Self.Handle;
QueueWorkItem(InternalThreadFunction, Context);
finally
Context.Free;
end;
end;
procedure TfmMain.do_WM_User(var Msg: TMessage);
begin
ListBox1.Items.Add(Format('Sum = %d, n = %d', [Msg.WParam, Msg.LParam]));
end;
end.