به استفاده از این ابزار که برای Delphi نوشته شده است می توانید کارهای طولانی خود را در پشت زمینه انجام بدهید، بدون اینکه برنامه بایستد یا قفل کند. این ابزار با استفاده از Thread ها این کار را انجام می دهد.
محتویات
نصب
مراحل نصب این ابزار همانند سایر ابزار (یا component) های دلفی است. در صورتی که با این موارد آشنایی دارید، بخش بعدی را مطالعه کنید.
پس از اینکه کدهای این ابزار رو از ضمیمه این مقاله دریافت کردید، فایل ThreadWorkerPackage.dpk را در محیط Delphi باز کنید و بر روی پروژه کلیک راست کنید. سپس گزینه Install را انتخاب کنید. پس از کامپایل شدن، ابزار به طور خودکار نصب خواهد شد و پیغامی مبنی بر نصب موقعیت آمیز ابزار دریافت خواهید کرد.
از این پس ابزار در آخرین tab با نام SoftProjects قرار خواهد گرفت. در این tab ابزار را با نام TThreadWorker خواهید دید.
استفاده آسان
پس از نصب موفقیت آمیز، ابزار را در فرم قرار دهید. در بخش Event ها بر روی رویداد OnExecute دوبار کلیک کنید تا ویرایشگر رویداد جدیدی را با نام ThreadWorker1Execute ایجاد کند. در این رویداد است که باید کدهای خود را برای اجرا در پس زمینه بنویسید. تنها نکته ای که در اینجا مهم است عدم استفاده از پیغام ها یا MessageBox هست. این کار باعث اختلال در کار thread می شود.
به نمونه کد زیر توجه کنید که یک حلقه طولانی است در رویداد OnExecute نوشته شده است.
در این مثال در صورتی که از چنین حلقه ای در برنامه معمولی استفاده شود، برنامه برای مدت طولاتی متوقف خواهد شد. در حالی که اگر از کامپوننت ThreadWorker استفاده کنید می توانید همزمان با اجرای چنین کدی برنامه همچنان به فعالیت عادی خود ادامه بدهد.
procedure TfrmDemo.ThreadWorker1Execute;
var i:Integer;
begin
for I := 0 to 1000000 do begin
sleep(50);
end;
end;
رویداد OnExecute زمانی اجرا می شود که تابع StartWorking را فراخوانی نمایید که برای آغاز کار thread مورد استفاده است. در این رویداد می توانید از یک حلقه استفاده کنید تا برخی کارها را انجام دهید.
برای قرار دادن حلقه در این رویداد حتما باید مقدار ویژگی ShouldStop را بررسی کنید. این ویژگی در صورتی مقدار true را برمی گرداند که درخواستی برای پایان کار ارسال شده باشد. نمونه ای از استفاده از ShouldStop و حلقه را نشان می دهد.
procedure TfrmDemo.ThreadWorker1Execute;
begin
while (Worker.ShouldStop = false) do
begin
sleep(100);
end;
end;
بررسی ویژگی های اصلی
برای راحتی کار با thread ها چندین تابع و رویداد در نظر گرفته شده است که در زیر توضیح داده می شوند.
متد StartWorking
این متد برای آغاز کار این کامپوننت مورد استفاده قرار می گیرد. بعد از اینکه رویداد OnExecute را تنظیم کردید این متد را فراخوانی کنید، در غیر این صورت هیچ اتفاقی نخواهد افتاد. پس از فراخوانی این متد رویداد OnExecute در یک thread جدید که برای این کار ایجاد شده است اجرا خواهد شد.
متد Stop
از این متد برای پایان کار این کامپوننت استفاده کنید. قبل از فراخوانی این متد باید متد StartWorking را فراخوانی کرده باشید، در غیر اینصورت هیچ اتفاقی نخواهد افتاد. این متد کار thread را به یکباره پایان خواهد داد و منتظر پایان یافتن کار آن نخواهد ماند. در صورتی که می خواهید کار thread به یکباره به پایان نرسد از متد StopRequest استفاده کنید.
متد StopRequest
از این متد برای پایان ارسال درخواست پایان کار کامپوننت استفاده کنید. با فراخوانی این متد بلافاصله thread بسته نخواهد شد، بلکه ویژگی ShouldStop مقدار true به معنی درخواست پایان کار قرار خواهد گرفت. با این کار می توان اعمال آزاد سازی حافظه و موارد دیگر را قبل از پایان دادن به کار انجام دهید. توجه کنید حتما باید در رویداد OnExecute مقدار این ویژگی ShouldStop را بررسی کنید، در غیر اینصورت این متد هیچ نتیجه ای نخواهد داشت.
متد های Suspend و Resume
متد Suspend برای تعلیق اجرای thread استفاده کنید. به این معنی که تمام کاری که در thread و در رویداد OnExecute در حال انجام بودید به صورت موقت متـوقف خواهد شد. استفاده از این متد ممکن برای مواردی که لازم است تا کار های دیگر موقتا متوقف شود تا کار مورد نظر را سریع تر انجام داد. برای ادامه اجرای thread باید متد Resume را اجرا کنید.
متد Resume برای ادامه اجرای thread استفاده کنید. در صورتی که قبلا متد Suspend را فراخوانی کرده باشید کارها تماما متوقف هستند و با استفاده از فراخوانی این تابع یعنی Resume به کار خود و دقیقا از محل قبلی ادامه خواهند داد. فراخوانی این متد در حالت عادی هیچ تاثیری نخواهد شد.
ویژگی Speed
این ویژگی اولویت اجرای thread را تعیین می کند. اولیت اجرا ویژگی مربوط به Thread ها است که باعث میشود تا زمانی که سیستم عامل برای اجرا دستورات یک thread می دهد نسبت سایر thread ها کمتر یا بیشتر باشد. برای اطلاعات بیشتر در این زمینه به مستندات MSDN بخش Threading مراجعه کنید.
این ویژگی مقادیر زیر را بر حسب اولیت میگیرد: tpIdle برای کمترین اولویت ، tpNormal برای اولیت عادی و پیش فرض و tpTimeCritical حداکثر اولویت و استفاده از زمان واقعی CPU قابل استفاده هستند. برای لیست کامل موارد به راهنمای دلفی بخش TThreadPriority مراجعه کنید.
ویژگی IsBusy
این ویژگی تعیین می کند که آیا کار thread به پایان رسیده است یا نه. پس از فراخوانی متد StartWorking و قبل از پایان کار OnExecute مقداری که این ویژگی برمی گرداند true خواهد بود.
ویژگی IsSuspended
این ویژگی تعیین می کند که آیا thread به حالت معلق یا Suspended در آمده است یا نه. پس از فراخوانی متد StartWorking و سپس Suspend مقداری که این ویژگی برمی گرداند true خواهد بود.
ویزگی ShouldStop
این ویزگی تعیین می کند درخواستی برای پایان کارها رسیده است یا نه. این ویزگی را در درون حلقه و در درون رویداد OnExecute استفاده کنید. مقدار این ویزگی پس از فراخوانی متد StopRequest مقدار true خواهد بود.
سایر متد ها
در زیر تعدادی متد برای کار با اشیا در درون چندین thread در نظر گرفته شده است. از انجایی که ویرایش و تغییر ویژگی های برخی اشیا مانند کنترل ها از درون چندین thread به علت مشکلاتی که ممکن است به وجود بیاورد صحیح نیست، چندین متد برای این رفع این مشکل در نظر گرفته شده است. این متد ها که Queue و Synchronize نام دارند متدی دیگر را به عنوان ورودی دریافت می کنند که با ارسال آن به thread اصلی برنامه آن ها را در آنجا اجرا می کنند. اجرا کردن این توابع ارجاع داده شده مشکل دسترسی چندین thread به کنترل ها را حل خواهد کرد، زیرا این توابع در رویه و thread اصلی که کنترلها نیز در آن تعریف شده اند فراخوانی خواهند شد.
متد Synchronize
ورودی از نوع متد (procedure of object)
این متد آدرس آروگان ورودی خود را که آدرسی از یک متد است، دریافت می کند تا همانطور که گفته شد آن را برای اجرا به thread اصلی برنامه ارسال کند. به مثالی توجه کنید:
procedure TfrmDemo.UpdatePosition;
begin
barProgress.Position:=barProgress.Position+1;
end;
procedure TfrmDemo.ThreadWorker1Execute;
begin
while (Worker.ShouldStop=false) and ( barProgress.Position+1<=barProgress.Max) do
begin
Worker.Synchronize(UpdatePosition);
end;
end;
فراخوانی متد Synchronize سبب خواهد تا thread تا زمان آغاز اجرای تابع مورد درخواست که در این مثال UpdatePosition نام دارد، منتظر بماند و پس از آغاز اجرای آن در thread خود به کارش به طور همزمان ادامه دهد.
متد Queue
ورودی از نوع متد (procedure of object)
دقیقا همانند متد Synchronize عمل می کند با یک تفاوت و آن اینکه آرگومان ورودی این متد به لیستی برای اجرا در thread اصلی اضافه می شود. این لیست به ترتیب ورود در thread اصلی برنامه اجرا خواهد شد ولی ممکن این عمل کمی طول بکشد با این حال برخلاف عملکرد متد Synchronize در متد Queue منتظر نخواهد ماند اجرای آن آغاز بشود و به کار خود ادامه خواهد داد.
با این اوصاف در کار با متد Queue ممکن است با مشکل همزمانی دسترسی مواجه شوید. با این حال این متد سرعت کار thread را به علت انتظار بی مورد پایین نخواهد آورد.
نمونه پروژه ضمیمه مقاله
در این نمونه پروژه سعی شده متد های اصلی پیاده سازی شود. در این پروژه برای افزودن به مقدار یک progressBar از این ابزار استفاده شده است. برای افزودن این مقدار از متد Synchronize استفاده شده است.