PDA

View Full Version : جلوگیری از فریز شدن فرم درهنگام اجرای quary



arshia_
شنبه 27 آبان 1385, 12:30 عصر
سلام
من در حال نوشتن یه برنامه آمارگیری هستم
در قسمتهایی از برنامه پرس و جوهای خیلی پیچیده ای استفاده می شه که حداقل چند دقیقه از زمان درخواست مقادیر از بانک تا پردازش و دریافت اطلاعات زمان صرف می شه و برنامه در تمام این مدت )فرم رو فریز می کنه و کاربر تصور می کنه برنامه هنگ کرده
timer,progressbar هم در تمام این مدت هیچ فعالیتی نمی تونه انجام بده
چه روشی به کار بگیرم تا در هنگام اجرای پرس و جو از بانک فرم حالت معمول رو حفظ کنه و حتی اگر کاربر تمایل داشت بتونه اونو لغو کنه؟

ghabil
شنبه 27 آبان 1385, 13:01 عصر
واسه اینکه فریز نکنه که راحت میتونی یک ترد جدید بسازی و بگی کوئری رو تردت اجرا کنه . اما اینکه بتونی کنسلش کنی هم خوب میتونی ترده رو ساسپندش کنی، حالا بجز این چند وقت پیشا اینجا یک بحثی بود که چه جوری میشه برای این کوئری ها پروگرس بار گذاشت که بالاخره یک راهی گیر آورده بودند انگار...

MNosouhi
شنبه 27 آبان 1385, 13:41 عصر
چه روشی به کار بگیرم تا در هنگام اجرای پرس و جو از بانک فرم حالت معمول رو حفظ کنه و حتی اگر کاربر تمایل داشت بتونه اونو لغو کنه؟
علاوه بر روشی که گفته شد ، راههای دیگری هم وجود داره ، مثلا برای اینکه فرمت فریز نشه در بین دستوراتت از Application.ProcessMessages استفاده کن و برای اینکه کاربر بتونه عملیات رو لغو کنه ، در بین دستورات برنامت یه متغیر بولین رو چک کن که اگه مثلا True بود با تابع Exit از تابع خارج بشه (یا اگه که با Transaction کار میکنی Rollback کنه) .

mzjahromi
شنبه 27 آبان 1385, 13:56 عصر
علاوه بر روشی که گفته شد ، راههای دیگری هم وجود داره ، مثلا برای اینکه فرمت فریز نشه در بین دستوراتت از Application.ProcessMessages استفاده کن و برای اینکه کاربر بتونه عملیات رو لغو کنه ، در بین دستورات برنامت یه متغیر بولین رو چک کن که اگه مثلا True بود با تابع Exit از تابع خارج بشه (یا اگه که با Transaction کار میکنی Rollback کنه) .
این برای حالتیه که دستورات درون حلقه اجرا بشن یا اینکه چند دستور داشته باشید و بینشون بتونی این کارا رو انجام بدی
زمانیکه یک دستور برای اجرا داری و همون یک دستور طولانی میشه این روش کاربردی نداره

m-khorsandi
شنبه 27 آبان 1385, 14:41 عصر
به غیر از موردی که ghabil گفت، که البته فکر میکنم کار ساده ای نباشه،اگه با ADO کار میکنی میتونی
از ویژگی ConnectionOptions مربوط به ADOConnection به همراه ExecuteOptions مربوط به ADOTable یا ADOQuery
استفاده کنی.

ADOConnection.ConnectionOptions یه گزینه به نام coAsyncConnect داره که باعث میشه در زمان بازیابی
اطلاعات ، اینکار به صورت غیرهمزمان انجام بشه.

ADOQuery.ExecuteOptions رو هم نسبت به نوع کاری که میخوای انجام بدی باید تنظیم کنی،
مثلا" برای بازیابی رکوردها باید از eoAsyncFetch استفاده کنی.

به همراه Property ها از چند تا Event هم میتونی استفاده کنی:
OnFetchComplete
OnFetchProgress

این لینک هم میتونه کمکت کنه :

Title: TADOConnection (http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21480381.html)

arshia_
یک شنبه 28 آبان 1385, 11:19 صبح
ممنون از پاسخ ها
همونطور که آقای جهرمی گفت فقط در حالتی که چند تا دستور باشه می تونیم از روش Application.ProcessMessages کمک بگیریم
اما این فقط ی دستور اس کیو ال است که به خاطر حجم بالای اطلاعات آماری و پیچیده بودن کوئری بسیار زمانبر است
فکر می کنم روش استفاده از ترد بتونه کمک کنه
من یه ترد تعریف کردم و کد رو توی اون گذاشتم اما دوتا خطا از فایلهای sql , api ‌با پسوند dll أاد
ممکنه یه مثال از یه کوئری و ترد اینجا بذارین؟

ghabil
یک شنبه 28 آبان 1385, 17:54 عصر
این خطاهایی که میگی که نمیدونم چین و نباید هم بگیره ولی :
1) یک کلاس از TThread درایو کن
2) Executeش رو Override کن و توش بگو مثلا :


with MainForm.AnAdoDS do
begin
DisableControls;
try
Open;
finally
EnableControls;
end;
end;
Suspend;

3)یونیت Activex رو Use کن و CoinitilizeEx رو کال کن. (هرموقع از ADO بصورت مالتی ترد استفاده میشه باید کال بشه)
4) یک تابع بنویس که یک آبجکت از کلاس ترد بسازه (همون اول هم میتونی بگی Suspend نشده بسازه)

اصلا هم کار عجیب غریبی و مشکلی نیست (حداقل از Execute Plan نوشتن راحت تره فکر کنم)، کافی غلقش بیاد دستت، بیشتر مشکل کار هندل کردن اجرای پروسه های مالتی ترد هست که سیستم عامل داره برات انجام میده.
البته برای کارهای بزرگتر باید حواست باشه که باید مواظب باش برنامت ThreadSafe باشه.

کل اینچیزی که گفتم شاید 15 خط نشه .

MNosouhi
یک شنبه 28 آبان 1385, 20:23 عصر
آقای کوشا ، چه خوب می شد یه مثال میزدید.

arshia_
دوشنبه 29 آبان 1385, 09:08 صبح
ممنون می شم اگر یه مثال به این پست ضمیمه کنید
من راههایی رو که گفتید امتحان کردم ولی شاید روش کار من اشتباه بوده برای همین می خوام یه مثال داشته باشم
ADO باشه یا BDE فرقی نمی کنه

ghabil
دوشنبه 29 آبان 1385, 11:49 صبح
1) یک کلاس از TThread درایو کن




TestForm = Class(TForm);
....

TQryThrd = Class(TThread);
protected
Execute;override;
end;




2) Executeش رو Override کن و توش بگو مثلا :




procedure TQryThrd.Execute;
begin
with TestForm .AnAdoDS do
begin
DisableControls;
try
Open;
finally
EnableControls;
end;
end;
Suspend;
end;




3)یونیت Activex رو Use کن و CoinitilizeEx رو کال کن. (هرموقع از ADO بصورت مالتی ترد استفاده میشه باید کال بشه)



Uses ..., ActiveX;
...
TTestForm.onCreate
begin
CoinitilizeEx(nil);
end;



4) یک تابع بنویس که یک آبجکت از کلاس ترد بسازه (همون اول هم میتونی بگی Suspend نشده بسازه)



Button1.Click...
begin
TheQryThread := TQryThread.Create(False)//TheQryThread یک متغییر سراسری که بعدا هم خواستی بتونی از تردت استفاده کنی
ضمنا همینکه پارامتر False پاس شد موجب میشه که ترد به محض ایجاد فعال بشه...
end;