PDA

View Full Version : ناهماهنگی بین Thread و Progress



AliReza Vafakhah
چهارشنبه 04 آذر 1388, 20:31 عصر
سلام دوستان عزیز

من در برنامه باید 317 فایل رو جستجو کنم که این کار را با Thread کردم و می خوام در هین جستجو یک Progress هم به کاربر اعلام کنه صبر کنید و دائم به مقدار Max برسه و سپس صفر بشه ، خوب مشکل من اینجاست که وقتی از این Progress استفاده می کنم زمان کار Thread هم بیشتر میشه ! از دوستان پیشنهادی دارن که سرعت کار Thread پایین نیاد

آیا کار کرد Progress روی Thread تاثیر میگذاره ؟

{ ThrSearchFile }

procedure ThrSearchFile.Execute;
function GetNumberPage(const S:string):Integer;
var
i:Integer;
StrResult,Sm:string;
begin
for i:= 1 to Length(s) do
begin
Sm:=MidStr(s,i,1);
if ((Sm='-')or(Sm='.')) then Break;
StrResult:=StrResult+MidStr(s,i,1);
end;
Result:=StrToInt(StrResult);
end;

procedure SortArray();
var
i,j:Integer;
si,sj:Integer;
sTemp:string;
begin
for I := 0 to High(PageAddress) do
begin
ProgressA;
for j := 0 to High(PageAddress) do
begin
si:=GetNumberPage(PageAddress[i]);
sj:=GetNumberPage(PageAddress[j]);
if (si<sj) then
begin
sTemp:=PageAddress[i];
PageAddress[i]:=PageAddress[j];
PageAddress[j]:=sTemp
end;
end;
end;
end;
var
FindRec:TSearchRec;
i:Integer;
begin
i:=0;
if (FindFirst(GetCurrentDir+'\Book Scan\*.jpg',faAnyFile,FindRec)=0)then
begin
repeat
if (FindRec.Attr and faAnyFile)=FindRec.Attr then
begin
PageAddress[i]:=FindRec.Name;
inc(i);
ProgressA;
end;
until (FindNext(FindRec)<>0);
end;
FindClose(FindRec);
SortArray;
TForm1(Form1).sPanel1.Visible:=False;
TForm1(Form1).Enabled:=True;
end;

procedure ThrSearchFile.ProgressA;
begin
TForm1(Form1).PrgLoad.Position:=TForm1(Form1).PrgL oad.Position+50;
if (TForm1(Form1).PrgLoad.Position=TForm1(Form1).PrgL oad.Max) then
TForm1(Form1).PrgLoad.Position:=0
end;

vcldeveloper
چهارشنبه 04 آذر 1388, 22:25 عصر
این کد شما کلا اشکال داره؛ اولا اصلا نباید عناصر گرافیکی رابط کاربر رو در داخل کد Threadتان تغییر بدید، بارها درباره متد Synchronize و تکنیک های Synchronization در این تالار توضیح داده شده.
ثانیا، همه کد شما (بر فرض اینکه تغییر عناصر گرافیکی از داخل Threadایی غیر از Thread اصلی مجاز می بود) در داخل همین Thread اجرا میشه، یعنی همون Thread ایی که جستجو رو انجام میده، ProgressBar رو هم حرکت میده، پس طبیعی هست که با این کد، عملکرد ProgressBar روی جستجوی شما تاثیر بزاره.

AliReza Vafakhah
پنج شنبه 05 آذر 1388, 02:42 صبح
آقای کشاورز مشکلم حل شد ممنون

اما حقیقتا گیج شدم ، در این (http://www.barnamenevis.org/forum/showthread.php?t=79463) تاپیک آموزش Thread حرف از Synchronize شد که شما برای کار ها پیچیده ارسال پیام را عرض کردید خوب من قبل از این کار از دوتا Thread استفاده کردم و بین آنها Synchronize کردم (البته اگه Synchronize رو درست متوجه شده باشم) اما باز هم همان زمان زیاد افزوده میشود تا اینکه از ارسال پیغام استفاده کردم و مشکلم حل شد .

اما متوجه نشدم چرا ؟؟


این هم کد برنامه ام

{ ThrSearchFile }

procedure ThrSearchFile.Execute;
function GetNumberPage(const S:string):Integer;
var
i:Integer;
StrResult,Sm:string;
begin
for i:= 1 to Length(s) do
begin
Sm:=MidStr(s,i,1);
if ((Sm='-')or(Sm='.')) then Break;
StrResult:=StrResult+MidStr(s,i,1);
end;
Result:=StrToInt(StrResult);
end;

procedure SortArray();
var
i,j:Integer;
si,sj:Integer;
sTemp:string;
begin
for I := 0 to High(PageAddress) do
begin
PostMessage(Form1.Handle,TM_MYTHREAD_MSG,PRG_START ,0);
for j := 0 to High(PageAddress) do
begin
si:=GetNumberPage(PageAddress[i]);
sj:=GetNumberPage(PageAddress[j]);
if (si<sj) then
begin
sTemp:=PageAddress[i];
PageAddress[i]:=PageAddress[j];
PageAddress[j]:=sTemp
end;
end;
end;
end;
var
FindRec:TSearchRec;
i:Integer;
begin
i:=0;
if (FindFirst(GetCurrentDir+'\Book Scan\*.jpg',faAnyFile,FindRec)=0)then
begin
repeat
if (FindRec.Attr and faAnyFile)=FindRec.Attr then
begin
PageAddress[i]:=FindRec.Name;
inc(i);
PostMessage(Form1.Handle,TM_MYTHREAD_MSG,PRG_START ,0)
end;
until (FindNext(FindRec)<>0);
end;
PostMessage(Form1.Handle,TM_MYTHREAD_MSG,PRG_START ,0);
FindClose(FindRec);
SortArray;
Terminate;
end;

و کد تابع پیغام

procedure TForm1.MessgToProgress(var MSG: TMessage);
begin
case MSG.WParam of
PRG_START:
begin
Form1.PrgLoad.Position:=Form1.PrgLoad.Position+15;
end;
end;
end;

vcldeveloper
پنج شنبه 05 آذر 1388, 02:53 صبح
خوب من قبل از این کار از دوتا Thread استفاده کردم و بین آنها Synchronize کردم (البته اگه Synchronize رو درست متوجه شده باشم) اما باز هم همان زمان زیاد افزوده میشود تا اینکه از ارسال پیغام استفاده کردم و مشکلم حل شد .
متد Synchronize فقط بین Thread اصلی برنامه، و Thread مورد نظر شما کار میکنه، نه بین هر دو Thread ایی که شما مشخص کرده باشید.

کدهای مربوط به تغییر رابط گرافیکی کاربر فقط باید توسط Thread اصلی برنامه اجرا بشند.

در ضمن، در پایان متد Execute نیازی به نوشتن Terminate نیست؛ با پایان یافتن اجرای متد Execute، اون Thread خودش Terminate میشه.