작업을 수행하기 위해 여러 스레드를 실행해야하는 콘솔 응용 프로그램을 만들고 있습니다. 내 문제는 스레드가 차례 차례로 실행되고있는 것보다 하나씩 (thread1의 start -> work -> end 그리고 오직 thread2를 시작 함) 실행된다는 것입니다. 또한 나는 같은 시간 (성능 문제)에서 작동하도록 10 개 이상의 스레드를 원하지 않습니다. Bellow는 콘솔 응용 프로그램과 사용 된 데이터 모듈의 예제 코드입니다. 내 응용 프로그램도 같은 방식으로 작동합니다. 쓰레드가 끝나면 그 정보로 데이터베이스를 채워야하기 때문에 데이터 모듈을 사용했습니다. 또한 뭔가를하기위한 이유 인 설명을위한 코드에 주석이 있습니다.왜이 콘솔 응용 프로그램에서 스레드가 순차적으로 실행됩니까?
응용 프로그램 콘솔 코드 :
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils,
Unit1 in 'Unit1.pas' {DataModule1: TDataModule};
var dm:TDataModule1;
begin
dm:=TDataModule1.Create(nil);
try
dm.execute;
finally
FreeAndNil(dm);
end;
end.
및
unit Unit1;
interface
uses
SysUtils, Classes, SyncObjs, Windows, Forms;
var FCritical: TRTLCriticalSection;//accessing the global variables
type
TTestThread = class(TThread)
protected
procedure Execute;override;
end;
TDataModule1 = class(TDataModule)
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Déclarations privées }
public
procedure execute;
procedure CreateThread();
procedure Onterminatethrd(Sender: TObject);
end;
var
DataModule1 : TDataModule1;
FthreadCount : Integer; //know how many threads are running
implementation
{$R *.dfm}
{ TTestThread }
procedure TTestThread.Execute;
var
f : TextFile;
i : integer;
begin
EnterCriticalSection(fcritical);
AssignFile(f, 'd:\a' + inttostr(FthreadCount) + '.txt');
LeaveCriticalSection(fcritical);
Rewrite(f);
try
i := 0;
while i <= 1000000 do // do some work...
Inc(i);
Writeln(f, 'done');
finally
CloseFile(f);
end;
end;
{ TDataModule1 }
procedure TDataModule1.CreateThread;
var
aThrd : TTestThread;
begin
aThrd := TTestThread.Create(True);
aThrd.FreeOnTerminate := True;
EnterCriticalSection(fcritical);
Inc(FthreadCount);
LeaveCriticalSection(fcritical);
aThrd.OnTerminate:=Onterminatethrd;
try
aThrd.Resume;
except
FreeAndNil(aThrd);
end;
end;
procedure TDataModule1.Onterminatethrd(Sender: TObject);
begin
EnterCriticalSection(fcritical);
Dec(FthreadCount);
LeaveCriticalSection(fcritical);
end;
procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
InitializeCriticalSection(fcritical);
end;
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
DeleteCriticalSection(fcritical);
end;
procedure TDataModule1.execute;
var
i : integer;
begin
i := 0;
while i < 1000 do
begin
while (FthreadCount = 10) do
Application.ProcessMessages;//wait for an thread to finish. max threads at a //time =10
CreateThread;
EnterCriticalSection(fcritical);
Inc(i);
LeaveCriticalSection(fcritical);
while FthreadCount > 0 do //wait for all threads to finish in order to close the //main thread
begin
Application.ProcessMessages;
CheckSynchronize;
end;
end;
end;
end.
그래서, 내가 문제가 내 스레드가 다른 후 하나를 실행하고, 대신 모든 작업하는 것입니다 말했듯이 데이터 모듈 코드 같은 시간. 또한 때로는 첫 번째 스레드 만 작동한다는 것을 알았습니다. 나머지는 모두 만들고 완료했습니다. 내 응용 프로그램에서 모든 코드는 try-excepts로 보호되지만 오류는 발생하지 않습니다.
누군가가 조언을 해줄 수 있습니까?
* 세마포어 *를 사용하면 스레드를 한 번에 10 개 이상 실행할 수 있습니다. 스레드를 생성하기 전에 그것을 획득하고 각 스레드가 종료시이를 해제하게하십시오. 이미 10 개의 쓰레드가 실행 중이라면, 세마포어를 얻으려는 11 번째 시도는 다른 쓰레드가 종료 할 때까지 블록 될 것이다. 그런 다음 ProcessMessages busy-wait 루프가 필요하지 않습니다. 이러한 루프는 아무 것도하지 않고 애플리케이션이 결코 메시지를 보내지 않으므로 CPU 시간을 소비하므로 결코 처리 할 수있는 것이 없습니다. –
당신이 취할 수있는 또 다른 단계는 실제로 동기화 할 대상이있을 때만'CheckSynchronize'를 호출하는 것입니다. 세마포어를 설정하고, 세마포어 핸들과 전역'SyncEvent' 변수에서 MsgWaitForMultipleObjects를 호출하십시오. Classes.pas에서 읽어보십시오. 세마포어가 신호를 받으면 새 스레드를 만듭니다. 이벤트가 발생하면 CheckSynchronize를 호출하십시오. –
롭, 정보를 제공해 주셔서 감사합니다. 나는 세마포어를 읽었지만 어떻게 구현해야하는지 완전히 이해하고 있는지 확신 할 수 없다. 내가 뭘 읽었는지 WaitForSingleObject (무한, 처리)를 사용해야합니다 - 전체주기를 완료하는 스레드에 대한,하지만 어떻게 다른 스레드를 시작할 때 알 수 있습니까? 나는 10 개의 쓰레드로 세마포어를 만들어야한다고 생각하기 때문에 몇 가지 예제를 보았습니다.하지만 새 쓰레드를 만드는 방법을 줄이고 세마포어로 점심을 줄이는 방법은? 내 예제를 기반으로 약간의 예제를 제공 할 수 있습니까? 미리 감사드립니다. – RBA