PDA

View Full Version : کار Application.ProcessMessages چیه؟



mbshareat
چهارشنبه 08 دی 1389, 10:40 صبح
با سلام خدمت دوستان:قلب:
چندی پیش تو برنامه ناگزیر بودم برنامه رو در اثنای کار خاتمه بدم به طوری که حتی ادامه کد پروسیجر فراخوانی کننده ی پروسیجری که قراره برنامه از داخلش متوقف شه، اجرا نشه . از Application.Terminate استفاده کردم اما برنامه با تاخیر خاتمه یافت.جناب آقای تاجیک فرمودند اجرای این کد در لیست انتظار قرار می گیرد.
حالا سوال من این است که آیا می توان با اجرای Application.ProcessMessages انتظار داشت که اجرای برنامه فوراً متوقف شه؟
سوال دیگرم در مورد این دستور این است که آیا می توان برای Refresh کردن Label یا نمایش فرم هنگامی که به محض اجرای برنامه، یک حلقه از کدِ زمان بر اجرا می شه، از Application.ProcessMessages استفاده کرد؟
من کدی مثل این دارم:


Procedure TEasyTreeForm.A();
Begin
For I:=..
Begin
..
B();
If Application.Terminated=True Then
Exit;
..
En;
End;
Procedure TEasyTreeForm.B();
Begin
..
If ErrorTest=True Then
Begin
ShowMessage(..);
EndProgram(N,M);
Exit;
End;
..
End;
procedure TEasyTreeForm.EndProgram(FileNo,Byte:SmallInt);
Begin
GotoFed(Files[FileNo].Name,Byte); //رفتن به محیط داس و موقعیت خطا
Application.Terminate;
Application.ProcessMessages;
End;
به نظر شما با این کد می شه توقع داشت کدهای بعد از بررسی وجود خطا(ErrorTest) در پروسیجر A و B اجرا نشه؟:متفکر:
البته خودم حواسم هست که چندتا سوال کردم ولی همه با هم مرتبط بودند.در هر صورت از توجهتون ممنونم.
----
در یکی از سایتها این روایت رو دیدم:
از امام حسین (ع) پرسیدند: ادب چیست؟
فرمود: این است که از خانه خود بیرون آیی و با هیچ کس برخورد نکنی مگر آنکه او را برتر از خود ببینی.

AliReza Vafakhah
چهارشنبه 08 دی 1389, 11:47 صبح
یه سرچ میزدید

http://barnamenevis.org/showthread.php?32466-Application.ProcessMessages-%D8%AF%D9%82%DB%8C%D9%82%D8%A7-%D8%AF%D8%B1-%DA%86%D9%87-%D9%85%D9%88%D8%A7%D8%B1%D8%AF%DB%8C-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D9%85%DB%8C-%D8%B4%D9%88%D8%AF%D8%9F

http://barnamenevis.org/showthread.php?267346-%DA%A9%D8%A7%D8%B1-Application.ProcessMessages-%DA%86%DB%8C%D9%87%D8%9F

mbshareat
چهارشنبه 08 دی 1389, 17:52 عصر
با سلام:قلب:
از جناب AliReza Vafakhah (http://barnamenevis.org/member.php?74110-AliReza-Vafakhah) ممنونم.
البته من خودم Help رو خونده بودم. راستش هم می خواستم مطمئن بشم درست فهمیدم هم می خواستم ببینم کد من برای پایان دادن به برنامه و جلوگیری از اجرای بقیه کد مفیده یانه و Application.terminated کی True می شه؟آیا به محض اجرای Application.terminate؟ چون با چنین کدی هنوز هم کمی طول می کشید برنامه خودشو جمع و جور کنه و گاهی هم به محیط داس نمی رفت یا دوبار می رفت!

Felony
چهارشنبه 08 دی 1389, 22:04 عصر
متد ProcessMessages از شئ Application باعث ایجاد وقفه در کار پردازش های معمول برنامه میشه و Main Thread رو وادار به پردازش پیغام های داخل صف برنامه میکنه ، این روند تا خالی شدن صف پیغام ها ادامه داره ، بعد از خالی شدن صف پیغام ها روند اجرای برنامه به صورت معمول ادامه پیدا میکنه .

mbshareat
پنج شنبه 09 دی 1389, 18:05 عصر
با سلام و عرض ادب خدمت بزگان
ببخشید آقای تاجیک به نظر شما آیا در کدی که گذاشتم بررسی Application.Terminated در پروسیجر ( )A معنی دارد؟
یا برنامه در همان خط Application.ProcessMessages متوقف می شود و در خط آخر پروسیجر EndProgram اجرای برنامه کاملا خاتمه می یابد و نوبت به بررسی terminated نخواهد رسید؟:متفکر:

Felony
جمعه 10 دی 1389, 07:56 صبح
بله تائثیر داره ؛ اگر برنامتون در حال انجام بک عملیات سنگین باشه Main Thread مشغول هست و همونطور که گفتم Application.Terminate پیغام خروج رو در صف پیغام ها قرار میده ، اون چک باعث میشه اگه پیغام خروج ارسال شده بود اجرای حلقه رو بشکنه ، وقتی Application.Terminate رو صدا میزنید و پیغام WM_Quit به صف ارسال میشه ، با فراخوانی Application.ProcessMessages بررسی میشه اگر پیغام WM_Quit تو صف بود اونوقت Application.Terminated با True مقداردهی میشه ، شما وظیه دارید هرجایی که عملیات سنگینی انجام میدید بررسی کنید اگر Application.Terminated مقدارش True بود یعنی برنامه سعی در بسته شدن داره و باید روند اجرا کد زمان برتون رو متوقف کنید تا برنامه بتونه Terminate بشه .

mbshareat
شنبه 11 دی 1389, 19:42 عصر
با سلام و عرض ادب
ببخشید اینقدر دیر به تاپیک سر زدم.(راستش همین الان هم کلی طول کشید تا بتونم صفحه تاپیک رو ببینم)
جناب آقای تاجیک شما قبلا فرموده بودین:
متد ProcessMessages از شئ Application باعث ایجاد وقفه در کار پردازش های معمول برنامه میشه.
ولی طبق آخرین پستتون ظاهرا ProcessMessages کار برنامه رو متوقف نمی کنه.در نظر داشته باشین که تو کدم دارم:
Application.Terminate;
Application.ProcessMessages;

می بخشید یه سوال دیگه هم دارم:آیا Close فرم اصلی موجب توقف بلادرنگ اجرای برنامه می شه؟

mohsen24000
شنبه 11 دی 1389, 20:05 عصر
این پروسه رو هم تست کن


procedure Halt [ ( Exitcode: Integer) ];

Felony
شنبه 11 دی 1389, 21:26 عصر
با سلام و عرض ادب
ببخشید اینقدر دیر به تاپیک سر زدم.(راستش همین الان هم کلی طول کشید تا بتونم صفحه تاپیک رو ببینم)
جناب آقای تاجیک شما قبلا فرموده بودین:
متد ProcessMessages از شئ Application باعث ایجاد وقفه در کار پردازش های معمول برنامه میشه.
ولی طبق آخرین پستتون ظاهرا ProcessMessages کار برنامه رو متوقف نمی کنه.در نظر داشته باشین که تو کدم دارم:
Application.Terminate;
Application.ProcessMessages;

می بخشید یه سوال دیگه هم دارم:آیا Close فرم اصلی موجب توقف بلادرنگ اجرای برنامه می شه؟

من تناقضی بین پستهام نمیبینم ، گفتم وقتی Application.Terminate رو فراخوانی میکنید پیغام WM_Quit به صف پیغام ها ارسال میشه ، وقتی Application.ProcessMessage رو فراخوانی میکنید روند اجرای برنامه از حالت عادی خارج میشه و Main Thread پیغام های در حال انتظار در صف رو پردازش میکنه و وقتی کار پردازش پیغام های منتظر در صف تمام شد به روند عادی خودش ادامه میده ، اگر تو صف پیغام WM_Quit باشه با فراخوانی Application.ProcessMessages مقدار Application.Terminated با True مقدار دهی میشه ، حالا شما تو کدهایی که زمان بر هستند باید مقدار Application.Terminated رو بعد از فراخوانی Application.ProcessMessages بررسی کنید اگر True بود یعنی برنامه قصد بسته شدن داره و شما باید از عملیات زمان برتون صرف نظر کنید و خارج شید ( Exit یا ... ) .

حالا کجای گفته های قبلیم با پست آخریم تناقض داشت نمیدونم !

در مورد فراخوانی Close هم خیر ، خود Close در آخر Application.Terminate رو صدا میزنه ، یعنی در آخر WM_Quit به صف پیغام ها ارسال میشه .

mbshareat
یک شنبه 12 دی 1389, 09:25 صبح
با سلام
جناب اقای تاجیک گرامی ظاهرا کلمه process هست که برام نامفهومه.
آخه اینکه برنامه فقط یه متغیر رو مقدار دهی کنه ولی کاری که خواسته شده که اتمام اجرای برنامه هست رو انجام نده کجاش شبیه پردازش هست؟:متعجب:
در ضمن برام عجیبه که terminate حتی متغیری که نام مشابهی داره رو هم مقدار دهی نکنه!:گیج:
در هر صورت از اینکه وقت گذاشتین برام توضیح دادین کمال تشکر رو دارم.:تشویق:

Felony
یک شنبه 12 دی 1389, 14:19 عصر
آخه اینکه برنامه فقط یه متغیر رو مقدار دهی کنه ولی کاری که خواسته شده که اتمام اجرای برنامه هست رو انجام نده کجاش شبیه پردازش هست؟
Application.ProcessMessages پیغام های داخل صف رو پردازش میکنه ، اگر داخل صف پیغام WM_Quit وجود داشته باشه Application.ProcessMessages اون رو بررسی و تشخیص میده و دراین زمان Application.Terminated رو True میکنه ، با این کار داره به شما اطلاع میده که حواستون باشه که برنامه سعی در بسته شدن داره ، حالا اگر تو برنامتون پردازش زمان گیری نباشه WM_Quit اجرا میشه و برنماه بسته میشه ولی اگر پردازش سنگینی وجود داشته باشه برنامه حق نداره اون رو ببنده ، اگر این کار رو بکنه با halt تفوتی نداره ! ، Application.ProcessMessages با True کردن Application.Terminated داره به شما میگه هر چه زودتر کار پردازش رو لغو کن و منابع پروژه رو آزاد کن ؛ شما هم به عنوان برنامه نویس وظیفه داری تو پردازش های زمان بر بعد از فراخوانی Application.ProcessMessages مقدار Application.Terminated رو بررسی کنید و اگر True بود پردازش رو لغو کنید .


در ضمن برام عجیبه که terminate حتی متغیری که نام مشابهی داره رو هم مقدار دهی نکنه!
نام مشابه ؟ Application.Terminate کجاش با Application.Terminated یکی هست ؟!

دیگه نمیدونم چه طور توضیح بدم ، از این واضح تر نمیشه !

vcldeveloper
یک شنبه 12 دی 1389, 16:52 عصر
حالا سوال من این است که آیا می توان با اجرای Application.ProcessMessages انتظار داشت که اجرای برنامه فوراً متوقف شه؟
نه؛ هر برنامه ایی در شرایط عادی قبل از اتمام کارش نیاز به یکسری پاکسازی ها و پردازش ها داره. اگر نیاز دارید که برنامه برای خروج درنگ نکنه، باید از Halt استفاده کنید. Halt به سیستم عامل اطلاع میده که به زور برنامه را ببنده. طبیعی هست که در شرایط عادی همچین درخواستی منطقی نیست.

روند اجرای Application.ProcessMessages به این صورت هست که این متد متدی با نام ProcessMessage را فراخوانی میکنه. این متد پردازش پیغام های رسیده به Application را برعهده داره، و متناسب با اینکه آیا پیامی هنوز در صف پیام های Application باقی مانده یا خیر، مقداری را برگشت میده. Application.ProcessMessages تا زمانی که پیامی در صف پیام های Application منتظر پردازش نباشه، متد ProcessMessage را فراخوانی میکنه. یکی از انواع پیام هایی که ممکنه به ProcessMessage برسه، پیام WM_QUIT هست. در صورت دریافت این پیام، ProcessMessage مقدار FTerminate را True میکنه.


FTerminate چرا True میشه؟

به این دلیل که شی Application یک حلقه در متد Run داره که این حلقه، حلقه اصلی پردازش پیام ها در برنامه هست. در سیستم عامل ویندوز، اصلی ترین کاری که یک پروسه انجام میده، پردازش پیام های دریافتی هست. این حلقه Run در شی Application، مرتبا متد HandleMessage را فراخوانی میکنه. اون متد هم ProcessMessage را فراخوانی میکنه، تا پیام های موجود در صف پردازش بشند. اگر پیامی در صف برای پردازش موجود نباشه، متد Idle فراخوانی میشه. متد Idle هم رویداد OnIdle را فراخوانی میکنه. این حلقه برای پردازش تک تک پیام های دریافتی اجرا میشه. خروج از حلقه زمانی اتفاق میافته که مقدار FTerminate برابر با True شده باشه.


وقتی Application.Terminate فراخوانی میشه، دقیقا چه اتفاقاتی رخ میده؟

تابع PostQuitMessage ویندوز فراخوانی میشه. این تابع به ویندوز اعلام میکنه که این پروسه آماده بسته شدن هست. ویندوز هم یک پیام WM_QUIT به پروسه ارسال میکنه. این پیام به حلقه موجود در متد Application.Run میرسه. این حلقه متد HandleMessage را فراخوانی میکنه. این متد هم متد ProcessMessage را فراخوانی میکنه. متد ProcessMessage متوجه میشه که پیام دریافتی WM_QUIT هست، پس مقدار FTerminate را برابر با True میکنه. اجرای برنامه به حلقه Application.Run بر میگرده. در این حلقه، مقدار FTerminate بررسی میشه. از اونجایی که این مقدار True هست، اجرای حلقه Application.Run متوقف میشه، و اجرای برنامه از متد Application.Run خارج میشه. از اینجا به بعد، VCL روتین های پاکسازی خودش را اجرا میکنه، و بخش Finalization یونیت های مختلفی که در سورس استفاده شدند هم اجرا میشه، در نهایت اجرای برنامه خاتمه پیدا میکنه.


در زمان اجرای یک کد زمانبر، فراخوانی Application.Terminate چه تاثیری در اجرای کد داره؟

به طور عادی، هیچی، چون Application.Terminate بلافاصله بعد از ارسال پیام، کنترل اجرا را به خط بعدی واگذار میکنه. در این حین، اگر فرصتی برای پردازش پیام ها بوجود بیاد، پیام WM_QUIT پردازش میشه، و اجرای برنامه خاتمه پیدا میکنه.

اگر بعد از اجرای Application.Terminate، متد Application.ProcessMessages فراخوانی بشه، چه اتفاقی میافته؟

اجرای مکرر Application.ProcessMessages باعث میشه که مرتبا اجرای کد زمانبر مورد نظر شما متوقف بشه، پس موجب کاهش کارایی کد شما میشه. از طرف دیگه، اجرای Application.ProcessMessages باعث میشه همه پیام های موجود در صف پردازش بشه، اما با توجه به توضیحات بالا، Application.ProcessMessages خودش یک حلقه را تا اتمام تمامی پیام های موجود در صف اجرا میکنه، یعنی پردازش WM_QUIT باعث نمیشه که اجرای Application.ProcessMessages بلافاصله متوقف بشه، بلکه اجرای اون حلقه تا اتمام پردازش تمامی پیام های موجود در صف ادامه پیدا میکنه. بعد از اون مجالی پیش میاد برای بررسی وضعیت FTerminate. پس اگر بعد از اجرای Application.Terminate متد Application.ProcessMessage فراخوانی بشه، اجرای کد زمانبر شما در همان مرحله متوقف میشه، اما خروج از برنامه بعد از پردازش پیام های موجود در صف پیام ها، و اجرای کدهای پاکسازی هست.



سوال دیگرم در مورد این دستور این است که آیا می توان برای Refresh کردن Label یا نمایش فرم هنگامی که به محض اجرای برنامه، یک حلقه از کدِ زمان بر اجرا می شه، از Application.ProcessMessages استفاده کرد؟
بله، می تونید از اون متد برای این کار استفاده کنید.



به نظر شما با این کد می شه توقع داشت کدهای بعد از بررسی وجود خطا(ErrorTest) در پروسیجر A و B اجرا نشه؟
نه، بررسی وضعیت Application.Terminated در کد شما ارزشی نداره، مگر اینکه کد شما در یک Thread جداگانه اجرا شده باشه.