Application.ProcessMssages چیست ؟
همونطور که میدونید اساس کار سیستم عامل ویندوز پیغام ها ( Messages ) هستند که توضیحات مربوطه در این مقاله نمیگنجه ، با صدا زدن متد ProcessMessages روند عادی اجرای کدهای برنامه فراخوان این متد معلق میشود و Main Thread برنامه ملزم به پردازش پیغام های موجود در صف برنامه میشود ، این روند پردازش پیغام ها تا خالی شدن کامل صف پیغام های مربوط به برنامه ( Main Thread ) ادامه پیدا میکند و پس از پردازش تمام پیغام های موجود در صف و انجام عملیات مربوط به اون ها برنامه به اجرای عادی کدهای قبلی خودش که اجرای اون ها با فراخوانی متد ProcessMessages معلق شده بود ادامه میده .

چرا نباید هرجایی از آن استفاده کرد ؟
با نوشتن کدی که بار پردازشی زیادی رو به برنامه تحمیل میکنه به دلیل Single Thread بودن برنامه های نوشته شده به صورت پیش فرض این کدهای زمان بر در نخ اصلی برنامه که وظیفه به روز رسانی رابط کاربری رو بر عهده داره اجرا میشن و چون این Thread مشغول اجرای این کدهای زمان بر هست نمیتونه به پیغام های به روز رسانی رابط کاربری رسیدگی کنه و عملا UI برنامه فریز میشه و برنامه موقتا تا پایان عملیات پردازش از دسترس خارج میشه ؛ مثلا کد زیر :

var
cycle: integer;
begin
inc(worklevel);
for cycle := 1 to 5 do
begin
Memo1.Lines.Add('- Work ' + IntToStr(worklevel) + ', Cycle ' +
IntToStr(cycle));
sleep(1000);
// some other work
end;
Memo1.Lines.Add('Work ' + IntToStr(worklevel) + ' ended.');
dec(worklevel);
end;


* متغییر worklevel رو در بخش private فرم برنامه از نوع Integer تعریف کنید .

خوب با نوشتن کد بالا داخل یک دکمه و زدن دکمه حلقه شروع به چاپ میکنه و رابط کاربری برنامه موقتا از دسترس خارج میشه ، ولی با این حال با کلیک دوباره روی دکمه برنامه از خودش عکس العملی نشون نمیده ولی سیستم عامل این کلیک رو در Message Queue برنامه ثبت میکنه تا برنامه در اولین فرصت بهش رسیدگی کنه ؛ یعنی شما اگر 3 بار روی دکمه کلیک کنید با اینکه رابطه کاربری برنامه غیر فعال هست ولی بعد از پایان هر دوره چاپ ( پایان حلقه ) به تعداد کلیک زده شده روی دکمه حلقه دوباره شروع به چاپ میکنه ، چون کلیک انجام شده روی دکمه به عنوان یک پیغام در Message Queue برنامه ثبت شده و تا زمانی که به این پیغام رسیدگی نشه از این صف حذف نمیشه .

حالا میخوایم با استفاده از متد ProcessMessage از شئ Application برنامه رو مجبور کنیم در هر بار دور زدن حلقه پیغام های داخل صف برنامه رو پردازش کنه و به اونها رسیدگی کنه تا رابط کاربری برنامه که پیغام های به روز رسانیش تو همین صف درج میشه از کار نیافته :

var
cycle: integer;
begin
inc(worklevel);
for cycle := 1 to 5 do
begin
Memo1.Lines.Add('- Work ' + IntToStr(worklevel) + ', Cycle ' +
IntToStr(cycle));
Application.ProcessMessages;
sleep(1000);
// or some other work
end;
Memo1.Lines.Add('Work ' + IntToStr(worklevel) + ' ended.');
dec(worklevel);
end;


خوب ؛ دوستان تازه وارد با مواجه شدن با هر نوع پردازش سنگینی که UI رو تحت تائثیر قرار میده بدون در نظر گرفتن شرایط خیلی راحت متد ProcessMessages رو صدا میزنن و کلی هم کیف میکنن که همه چیز درست شد ؛ مثل کد بالا !

خوب حالا که کد بالا رو داخل یک دکمه نوشتید برنامه رو اجرا کنید و روی دکمه چند بار کلیک کنید ( با فاصله های زمانی مختلف ) ، خوب ؟ با چه خروجی مواجه شدید ؟!

با اجرای کد بالا ترتیب اجرای کدها به صورت کامل به هم میریزه ، چون شما با صدا زدن متد ProcessMessages ماهیت صف رو زیر سوال بردید که البته با صدا زدن متد ProcessMessages این امری طبیعی هست ، مثل این میمونه که در یک نانوایی صف طوری باشه که نانوا به جای اینکه هر کی زودتر اومده تو صف بهش نان زودتر بده ، به هر کی که وارد صف میشه و داد میزنه من نان میخوام نون بده ، حالا 10 نفر هم جلوی اون طرفی که داد زده بودن ولی نون به اونی که داد زده میرسه و بعد به افراد داخل صف !

بی مهابا و بدون بررسی و اطمینان از صحت عملکرد برنامه متد ProcessMessages رو صدا نزنید ، اول بررسی کنید ببینید این متد میتونه تائثیر نامناسبی رو عملکرد برنامتون داشته باشه بعد ازش استفاده کنید ، گاهی اوقات این متد کارهای خارق العاده ای انجام میده که پیدا کردن دلیلشون نیاز به ساعت ها وقت داره .

در آخر استفاده از این متد در پروژه های کوچک ممکنه کار راه انداز باشه ولی در کل اصلا پیشنهاد نمیشه ، برای اجرای کدهای زمانبر و سنگین بهترین گزینه تردها هستند .

موفق باشید .