PDA

View Full Version : سوال: موازی سازی 3 ترد و راهکار بهینه برای آن



sajioo
سه شنبه 11 آذر 1393, 09:34 صبح
دوستان سلام و وقت بخیر به همگی
بنده طی آموزش های بسیار مفید سایت برنامه نویس :قلب: با ترد ها در دلفی تا حدودی آشنا شدم.
وقتی ترد از اشیای روی فرم استفاده نمیکنه خیلی خوب کار میده.
اما سوال من اینه
بنده 1 ترد نوشتم که برای مثال بر روی فرم یک من که 3 اسکرول باکس داره 10 تا پنل درست کنه.
نمونه کد رو در زیر قرار میدم.



Type MyThread = Class(TThread)
private
public
str:string;
control:string;
procedure p1;
procedure p2;
procedure p3;
protected
procedure Execute; override;
end;



//**********************************************

procedure MyThread.Execute;
begin
if control='p1' then
p1;
if control='p2' then
(p2);

if control='p3' then
(p3);
Exit;
end;

procedure mythread.p1;
var
command : TStringList ;
i:integer;
panel:TPanel;
begin
command := TStringList.Create();
try
Split('|',str, command);
finally




for i := command.Count - 1 downto 1 do
begin
panel:=TPanel.Create;
with panel do
begin
Parent:=form1.sScrollBox1;
Align:=altop;
Caption:=command[i];
end;
end;end;end;

///*****************************


procedure mythread.p2
;var
command : TStringList ;
i:integer;
panel:TPanel;
begin
command := TStringList.Create();
try
Split('|',str, command);
finally




for i := command.Count - 1 downto 1 do
begin
panel:=TPanel.Create;
with panel do
begin
Parent:=form1.sScrollBox2;
Align:=altop;
Caption:=command[i];
end;
end;end;end;
//***************************************


procedure mythread.p3;
var command : TStringList ; i:integer;
panel:TPanel;begin command := TStringList.Create(); try Split('|',str, command);
finally




for i := command.Count - 1 downto 1 do if (i mod 2) = 0 then begin
panel:=TPanel.Create;with panel dobegin Parent:=form1.sScrollBox3; Align:=altop; Caption:=command[i];end;
end;end;end;




خوب الان بعدش برای اجرا از کد زیر استفاده می کنم.





T:=MyThread.Create(true);
T.str:=str;
T.control:='p1';
T.FreeOnTerminate := True;
T.Execute;
T.Suspend;
T.Terminate;
T:=MyThread.Create(true);
T.str:=str;
T.control:='p2';
T.FreeOnTerminate := True;
T.Execute;
T.Suspend;
T.Terminate;
T:=MyThread.Create(true);
T.str:=str;
T.control:='p3';

T.FreeOnTerminate := True;
T.Execute;
T.Suspend;
T.Terminate;


خوب همانطور که مشاهده میکنید بنده کدهایم را اینطور نوشتم.
این کد درست کار میکند فقط یک مشکل دارد و آن اینکه اول صبر میکند و پنل های اسکرول 1 را میسازد سپس پنل های اسکرول 2 و سپس پنل های اسکرول 3.
بررسی زیاد کردم در پست های پیشین از Synchronize هم استفاده کردم که موثر واقع نشد و متوجه شدم که Synchronize ترد را پاس میدهد به ترد اصلی( البته به زبان ساده)
چه راه حلی دوستان برای موازی سازی این کار پیشنهاد میدهند و آیا اصولا راهی موجود است یا نه؟:متفکر:
بسیار تشکر:تشویق:

Mask
سه شنبه 11 آذر 1393, 10:11 صبح
برای یه همچین کاری چه نیاز به ترد هست.
استفاده از ترد برای مواقعی که برنامه کار سنگین و موازی انجام میدهد استفاده میشود.

sajioo
سه شنبه 11 آذر 1393, 10:22 صبح
خوب ماسک عزیز الان در این مواقع فرم تا اینا ساخته بشن قفل میشه.
فرض کن بجای 10 پنل 100 یا 1000 تا پنل باشه.
من میخوام اون حالت قفل شدن رخ نده و هر دو موازی هم ساخته بشن. البته نمی دونم امکانش هست یا حرف من درسته یا نه؟:متفکر:

یوسف زالی
سه شنبه 11 آذر 1393, 14:04 عصر
راهش ترد نیست.
استفاده از ترد هم این طوری نیست.
شما باید از دستوراتی استفاده کنید که برای ساخت اشیا روی فرم زمان کمتری بگیره.
مثلا همه اشیا رو هاید شده بسازید.
از متدهای سریع تری استفاده کنید.
از متدهای میانی برای آف کردن repaint استفاده کنید...
استفاده از ترد در این مواقع حتما می باید سینک شده باشه، در غیر اینصورت یکی در میون AV خواهید گرفت.

sajioo
سه شنبه 11 آذر 1393, 16:09 عصر
ممنون یوسف جان منظورت از جمله زیر چیست و اگر مقدوره برات یک مثال کوچک یا راهنمایی بنده رو انجام بده



از متدهای میانی برای آف کردن repaint استفاده کنید...
استفاده از ترد در این مواقع حتما می باید سینک شده باشه، در غیر اینصورت یکی در میون AV خواهید گرفت.

یوسف زالی
سه شنبه 11 آذر 1393, 19:55 عصر
یکی از مثالهاش رو ببین:


procedure TControl.Repaint;
var
DC: HDC;
begin
if (Visible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
Parent.HandleAllocated then
.
.

و موارد مشابه دیگه.
در بعضی موارد با دونستن ساز و کار درونی یک شی می تونیم استفاده بهینه تری ازش کنیم. مثلا در مورد Memo تست کنید ببینید فرق این دو کد چیه:


var
i: integer;
begin
Memo1.Clear;
for i := 1 to 10000 do
Memo1.Lines.Add(IntToStr(i));
end;



var
i: integer;
begin
Memo1.Lines.BeginUpdate;
Memo1.Clear;
for i := 1 to 10000 do
Memo1.Lines.Add(IntToStr(i));
Memo1.Lines.EndUpdate;
end;

در مورد فرم هم همینه، شما تا وقتی که اشیاتون قابل نمایش نیست فرم عکس العمل نمایشی نداره. عکس العمل نمایشی یکی از کند ترین کارهای فرم هست. اگر بتونید اون رو به تعویق بندازید یا همه رو یک جا انجام بدید، برد کردید.

در مورد AV یا همون Access Violation وقتی دارید روی یک شی VCL کار می کنید، نمی تونید همزمان دو تا کار روش انجام بدید، علی الخصوص این که اون دو تا کار به هم مربوط باشند.
در مورد کار شما، ساخت دو شی همزمان رو فرم به معنی آپدیت همزمان لیست اشیای فرمه، به طور دقیق تر، هر زمان که Owner یک شی رو روی فرم تنظیم می کنید، در لیست درونی نگه دارنده اون فرم دارید یک آیتم اضافه می کنید. همین طور برای Parent.
شما تا زمانی که Owner و Parent شی تون فرم رو کاری نداشته باشه مشکلی نخواهید داشت.
از طرفی بعد از ساخت یک شی نمی تونید Owner اون رو (به سادگی) تغییر بدید.
برای همین کلا بی خیال ساخت اشیا در ترد ها بشید.

در خصوص کار با ترد ها، کمی باید مراقب تر باشید.

lord_viper
شنبه 15 آذر 1393, 08:26 صبح
موقع ساخت اشیا میتونین تو حلقتون از دستور

application.processmessage

استفاده کنین تا برنامه به حالت هنگ نره

یوسف زالی
شنبه 15 آذر 1393, 09:42 صبح
از شما انتظار چنین جوابی نداشتم دیگه.
application . processmessage برای رفع مشکل ایشون هیچ راهکاری ارائه نمی ده.
ضمنا وسط کار کلیک ها و کارهای دیگه رو هم دخالت می ده.
اگر منظور از هنگ ، کمرنگ شدن فرمه، repaint گزینه خیلی خیلی بهتریه.

joker
شنبه 15 آذر 1393, 10:25 صبح
سلام
T:=MyThread.Create(false);

یوسف زالی
شنبه 15 آذر 1393, 11:28 صبح
منظورتون چیه از این کد؟