RyuLib/RyuLib for Delphi
ThreadPool
ryujt
2012. 1. 18. 06:05
쓰레드 클래스를 생성하지 않고 함수 호출만으로 쓰레드를 사용하기 위한 유닛입니다. "RyuLib for Delphi" 소스는 아래의 링크에서 받으시기 바랍니다.
http://ryulib.tistory.com/notice/11
사용법은 [소스 1]과 같습니다.
[소스 1]
1-6: 함수의 형태는 1-6: 라인과 같아야 합니다.
1: lpThreadParameter 인자는 쓰레드와 호출 객체가 서로 공유 할 데이터나 객체를 전달 받기 위한 것입니다. 필요없으면 사용하지 않아도 됩니다.
ThreadPool 유닛에는 [소스 2]와 같은 형태의 함수가 제공됩니다. 각각 필요한 작업에 따라 선택하시면 됩니다.
[소스 2]
[소스 3]은 1부터 n까지 더하는 프로그램을 멀티 쓰레드로 작성해 본 것 입니다. 속도를 줄이기 위해서 중간에 Sleep(1)로 쉬도록 했습니다. [그림 1]은 실행 결과 화면이며, 1000 --> 100 --> 10 순으로 계산을 했지만, 멀티 쓰레드이다 보니 먼저 계산 된 것부터 표시되고 있습니다. 가장 처음 입력한 수는 좀 큰 수였는데, 한 참 동안 계산이 안끝나서 중간에 캡쳐된 것을 올립니다.
[소스 3]
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.