आवेदन के अंधेरे पक्ष। ProcessMessages

मार्कस जुंगलास द्वारा प्रस्तुत लेख

जब डेल्फी में एक घटना हैंडलर प्रोग्रामिंग (जैसे) क्लिक पर एक TButton की घटना), वह समय आता है जब आपके आवेदन को थोड़ी देर के लिए व्यस्त होना चाहिए, उदा। कोड को एक बड़ी फ़ाइल लिखने या कुछ डेटा को संपीड़ित करने की आवश्यकता है।

यदि आप ऐसा करते हैं तो आप उस पर ध्यान देंगे आपका एप्लिकेशन लॉक होने लगता है. आपका फॉर्म अब और स्थानांतरित नहीं किया जा सकता है और बटन जीवन का कोई संकेत नहीं दिखा रहे हैं। लगता है दुर्घटनाग्रस्त हो गया।

कारण यह है कि एक डेल्पी एप्लिकेशन सिंगल थ्रेडेड है। आप जो कोड लिख रहे हैं, वह प्रक्रियाओं का एक गुच्छा है जो डेल्फी के मुख्य धागे द्वारा बुलाया जाता है जब भी कोई घटना होती है। बाकी समय मुख्य धागा सिस्टम संदेश और अन्य चीजें जैसे फॉर्म और घटक हैंडलिंग फ़ंक्शन संभाल रहा है।

इसलिए, यदि आप कुछ लंबा काम करके अपने इवेंट हैंडलिंग को पूरा नहीं करते हैं, तो आप उन संदेशों को संभालने के लिए एप्लिकेशन को रोक देंगे।

इस तरह की समस्याओं के लिए एक सामान्य समाधान कॉल करना है "अनुप्रयोग। ProcessMessages "। "एप्लिकेशन" TAPlication वर्ग का एक वैश्विक उद्देश्य है।

instagram viewer

आवेदन पत्र। प्रोसेसमेसेज सभी वेटिंग मैसेज को हैंडल करता है जैसे विंडो मूवमेंट, बटन क्लिक वगैरह। यह आमतौर पर आपके आवेदन "काम" रखने के लिए एक सरल समाधान के रूप में उपयोग किया जाता है।

दुर्भाग्य से "ProcessMessages" के पीछे के तंत्र की अपनी विशेषताएं हैं, जो बड़े भ्रम का कारण बन सकती हैं!

ProcessMessages क्या करता है?

PprocessMessages एप्लिकेशन संदेश कतार में सभी प्रतीक्षा प्रणाली संदेशों को संभालता है। विंडोज सभी चल रहे एप्लिकेशनों को "बात" करने के लिए संदेशों का उपयोग करता है। उपयोगकर्ता इंटरैक्शन को संदेशों के माध्यम से फ़ॉर्म में लाया जाता है और "प्रोसेसमेसेस" उन्हें संभालता है।

उदाहरण के लिए, यदि एक TButton पर माउस नीचे जा रहा है, तो ProgressMessages सभी इस घटना पर क्या होना चाहिए "दबाए गए" राज्य के लिए बटन को फिर से रंगना और, निश्चित रूप से, ऑनक्लिक () हैंडलिंग प्रक्रिया के लिए एक कॉल यदि आपने एक असाइन किया है।

यही समस्या है: ProcessMessages में किसी भी कॉल में किसी भी घटना हैंडलर को पुन: पुनरावर्ती कॉल हो सकती है। यहाँ एक उदाहरण है:

एक बटन के ऑनक्लिक यहां तक ​​कि हैंडलर ("काम") के लिए निम्नलिखित कोड का उपयोग करें। फॉर-स्टेटमेंट हर कॉल को प्रोसेसमेसेस के लिए एक लंबी प्रोसेसिंग जॉब देता है।

यह बेहतर पठनीयता के लिए सरल है:

{MyForm में}
कार्यसूची: पूर्णांक;
{OnCreate:}
कार्यसूची: = 0;
प्रक्रिया TForm1.WorkBtnClick (प्रेषक: Tobject);
वर
चक्र: पूर्णांक;
शुरू
इंक (वर्कवेल);
के लिये चक्र: = १ सेवा 5 कर
शुरू
Memo1.Lines। जोड़ें ('- कार्य' + IntToStr (WorkLevel) + ', चक्र' + IntToStr (चक्र);
आवेदन। ProcessMessages;
नींद (1000); // या कोई और काम
समाप्त;
Memo1.Lines। जोड़ें ('कार्य' + IntToStr (WorkLevel) + 'समाप्त हो गया।');
डेसी (वर्कवेल);
समाप्त;

"ProcessMessages" के बिना, निम्न पंक्तियों को मेमो को लिखा जाता है, अगर बटन को थोड़े समय में TWICE दबाया गया था:

 - काम 1, साइकिल 1
- काम 1, साइकिल 2
- काम 1, साइकिल 3
- काम 1, साइकिल 4
- काम 1, साइकिल 5
काम 1 समाप्त हुआ।
- काम 1, साइकिल 1
- काम 1, साइकिल 2
- काम 1, साइकिल 3
- काम 1, साइकिल 4
- काम 1, साइकिल 5
काम 1 समाप्त हुआ।

जबकि प्रक्रिया व्यस्त है, फॉर्म में कोई प्रतिक्रिया नहीं दिखाई देती है, लेकिन दूसरा क्लिक विंडोज द्वारा संदेश कतार में डाल दिया गया है। "OnClick" समाप्त होने के ठीक बाद इसे फिर से कॉल किया जाएगा।

"प्रोसेसमेसेस" को शामिल करना, आउटपुट बहुत अलग हो सकता है:

 - काम 1, साइकिल 1
- काम 1, साइकिल 2
- काम 1, साइकिल 3
- काम 2, साइकिल 1
- काम 2, साइकिल 2
- काम 2, साइकिल 3
- काम 2, साइकिल 4
- काम 2, साइकिल 5
काम 2 समाप्त हुआ।
- काम 1, साइकिल 4
- काम 1, साइकिल 5
काम 1 समाप्त हुआ।

इस बार यह फ़ॉर्म फिर से काम कर रहा है और किसी भी उपयोगकर्ता सहभागिता को स्वीकार करता है। तो बटन को आपके पहले "कार्यकर्ता" फ़ंक्शन AGAIN के दौरान आधे रास्ते में दबाया जाता है, जिसे तुरंत नियंत्रित किया जाएगा। आने वाली सभी घटनाओं को किसी अन्य फ़ंक्शन कॉल की तरह नियंत्रित किया जाता है।

सिद्धांत रूप में, "ProgressMessages" पर हर कॉल के दौरान किसी भी तरह के क्लिक और उपयोगकर्ता संदेश "जगह में" हो सकते हैं।

तो अपने कोड के साथ सावधान रहें!

विभिन्न उदाहरण (सरल छद्म कोड में!):

प्रक्रिया OnClickFileWrite ();
वर myfile: = TFileStream;
शुरू
myfile: = TFileStream.create ('myOutput.txt');
प्रयत्न
जबकि बाइट्सरिडी> 0 कर
शुरू
मेरी फाइल। लिखें (डेटाब्लॉक);
dec (बाइट्सरीड, साइज़ोफ़ (डेटाब्लॉक));
डेटाब्लॉक [2]: = # 13; {टेस्ट लाइन 1}
आवेदन। ProcessMessages;
डेटाब्लॉक [2]: = # 13; {परीक्षण पंक्ति २}
समाप्त;
आखिरकार
myfile.free;
समाप्त;
समाप्त;

यह फ़ंक्शन बड़ी मात्रा में डेटा लिखता है और हर बार डेटा के एक ब्लॉक को लिखे जाने पर "प्रोसेसमेसेज" का उपयोग करके एप्लिकेशन को "अनलॉक" करने की कोशिश करता है।

यदि उपयोगकर्ता फिर से बटन पर क्लिक करता है, तो उसी कोड को निष्पादित किया जाएगा जबकि फ़ाइल अभी भी लिखी जा रही है। तो फ़ाइल को 2 बार नहीं खोला जा सकता है और प्रक्रिया विफल हो जाती है।

हो सकता है कि आपका एप्लिकेशन कुछ त्रुटि पुनर्प्राप्ति करेगा जैसे बफ़र्स को मुक्त करना।

एक संभावित परिणाम के रूप में "डाटाब्लॉक" को मुक्त कर दिया जाएगा और पहला कोड "एक्सेस" का उल्लंघन करने पर "एक्सेस उल्लंघन" बढ़ाएगा। इस स्थिति में: टेस्ट लाइन 1 काम करेगा, टेस्ट लाइन 2 दुर्घटनाग्रस्त हो जाएगा।

बेहतर तरीका:

यह आसान बनाने के लिए आप पूरे फ़ॉर्म को "सक्षम: = गलत" सेट कर सकते हैं, जो सभी उपयोगकर्ता इनपुट को अवरुद्ध करता है, लेकिन उपयोगकर्ता को यह नहीं दिखाता है (सभी बटन ग्रे नहीं होते हैं)।

एक बेहतर तरीका यह होगा कि सभी बटन को "अक्षम" पर सेट किया जाए, लेकिन यह जटिल हो सकता है यदि आप उदाहरण के लिए एक "रद्द" बटन रखना चाहते हैं। इसके अलावा, आपको उन्हें निष्क्रिय करने के लिए सभी घटकों के माध्यम से जाने की आवश्यकता है और जब वे फिर से सक्षम होते हैं, तो आपको यह जांचने की आवश्यकता है कि क्या विकलांग अवस्था में कुछ शेष रहना चाहिए।

आप ऐसा कर सकते हैं सक्षम संपत्ति में परिवर्तन होने पर कंटेनर बच्चे को नियंत्रित करता है.

जैसा कि कक्षा का नाम "TNotifyEvent" बताता है, इसका उपयोग केवल घटना के लिए अल्पकालिक प्रतिक्रियाओं के लिए किया जाना चाहिए। समय लेने वाले कोड के लिए सबसे अच्छा तरीका IMHO है जो सभी "धीमे" कोड को एक थ्रेड में डालता है।

"PrecessMessages" और / या घटकों को सक्षम करने और अक्षम करने के साथ समस्याओं के बारे में, का उपयोग दूसरा धागा लगता है बहुत जटिल नहीं है।

याद रखें कि कोड की सरल और तेज़ लाइनें सेकंड के लिए भी लटका सकती हैं, उदा। डिस्क ड्राइव पर फाइल खोलने तक ड्राइव स्पिन खत्म होने तक इंतजार करना पड़ सकता है। यह बहुत अच्छा नहीं लगता है यदि आपका एप्लिकेशन क्रैश होता है क्योंकि ड्राइव बहुत धीमा है।

बस। अगली बार जब आप "एप्लिकेशन जोड़ें"। ProcessMessages ", दो बार सोचो;)

instagram story viewer