Tôi đang tạo một ứng dụng giao diện điều khiển cần chạy nhiều luồng để thực hiện tác vụ. Vấn đề của tôi là các chủ đề đang chạy cái khác (thread1 start -> work -> end và ONLY sau đó bắt đầu thread2) thay vì chạy tất cả cùng một lúc. Ngoài ra tôi không muốn nhiều hơn 10 chủ đề để làm việc trong cùng một thời gian (vấn đề hiệu suất). Dưới đây là một mã ví dụ về ứng dụng giao diện điều khiển và của datamodule được sử dụng. ứng dụng của tôi đang hoạt động theo cách tương tự. tôi đã sử dụng một datamodule bởi vì sau khi các chủ đề được hoàn thành tôi phải điền vào một cơ sở dữ liệu với những thông tin. Ngoài ra còn có ý kiến trong mã để giải thích đó là lý do để làm một cái gì đó.Tại sao các luồng chạy serially trong ứng dụng giao diện điều khiển này?
ứng dụng đang console:
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.
và datamodule đang
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.
như vậy, như tôi đã nói vấn đề là chủ đề của tôi đang chạy cái khác, thay vì làm việc tất cả trong cùng một lúc. tôi cũng đã thấy rằng đôi khi chỉ thread đầu tiên làm việc, sau đó tất cả phần còn lại chỉ tạo và hoàn thành. trong ứng dụng của tôi tất cả các mã được bảo vệ bởi try-excepts nhưng không có lỗi nào được nêu ra.
Ai đó có thể cho tôi lời khuyên không?
Một cách hay để đảm bảo rằng không quá 10 chuỗi chạy cùng một lúc là sử dụng * semaphore *. Có được nó trước khi tạo ra một sợi, và có mỗi thread phát hành nó khi chấm dứt. Nếu đã có 10 chủ đề đang chạy, thì nỗ lực thứ mười một để có được semaphore sẽ chặn cho đến khi một luồng khác chấm dứt. Sau đó, bạn không cần những vòng lặp bận chờ đợi của ProcessMessages. Những vòng lặp đó không làm gì ngoài việc ăn hết thời gian CPU vì ứng dụng của bạn không bao giờ gửi * bất kỳ tin nhắn nào, vì vậy sẽ không bao giờ có bất cứ thứ gì để xử lý. –
Một bước khác bạn có thể thực hiện là chỉ gọi 'CheckSynchronize' khi thực sự có điều gì đó để đồng bộ hóa với. Với thiết lập semaphore của bạn, hãy gọi MsgWaitForMultipleObjects trên tay cầm semaphore và biến 'SyncEvent' toàn cầu. Đọc về nó trong Classes.pas. Nếu semaphore được báo hiệu, hãy tạo một chuỗi mới. Nếu sự kiện được báo hiệu, hãy gọi CheckSynchronize. –
Rob, cảm ơn rất nhiều thông tin. Tôi đã đọc bây giờ về các ẩn dụ, nhưng tôi không chắc chắn rằng tôi hoàn toàn hiểu làm thế nào tôi nên thực hiện nó. từ những gì tôi đã đọc tôi cần phải sử dụng WaitForSingleObject (xử lý, vô hạn) - cho thread để hoàn thành toàn bộ chu kỳ, nhưng làm thế nào tôi có thể biết khi nào để bắt đầu một thread? tôi đã thấy một số ví dụ vì vậy tôi tin rằng tôi phải tạo semaphore với 10 chủ đề, nhưng khi giảm làm thế nào tôi tạo ra một chủ đề mới và ăn trưa nó trong semaphore? một số có thể cung cấp cho tôi một ví dụ nhỏ dựa trên ví dụ của tôi không? cảm ơn trước! – RBA