2008-09-30 8 views
20

क्या DoEvents का उपयोग किये बिना VB6.0 में लंबी चल रही प्रक्रिया को रद्द करना संभव है?DoEvents के बिना VB6.0 में एक लंबी चल रही प्रक्रिया को रद्द करना?

उदाहरण के लिए:

for i = 1 to someVeryHighNumber 
    ' Do some work here ' 
    ... 

    if cancel then 
     exit for 
    end if 
next 

Sub btnCancel_Click() 
    cancel = true 
End Sub 

मुझे लगता है मैं पहले "तो रद्द ..." वहाँ एक बेहतर तरीका है एक "DoEvents" की जरूरत है मान? यह थोड़ी देर हो गया है ...

उत्तर

28

नहीं, आपको यह सही लगता है, आप निश्चित रूप से अपने लूप में DoEvents चाहते हैं।

आप अपने मुख्य पाश में DoEvents रख दिया और पाते हैं कि बहुत ज्यादा प्रसंस्करण धीमा, Windows API समारोह GetQueueStatus (जो बहुत तेजी से DoEvents से है) जल्दी से निर्धारित करने के लिए अगर यह DoEvents कॉल करने के लिए भी आवश्यक है कॉल करने का प्रयास। GetQueueStatus आपको बताता है कि प्रक्रिया करने के लिए कोई घटना है या नहीं।

' at the top: 
Declare Function GetQueueStatus Lib "user32" (ByVal qsFlags As Long) As Long 

' then call this instead of DoEvents: 
Sub DoEventsIfNecessary() 
    If GetQueueStatus(255) <> 0 Then DoEvents 
End Sub 
7

क्या "फॉर" लूप जीयूआई थ्रेड में चल रहा है? यदि हां, तो आपको एक DoEvents की आवश्यकता होगी। आप एक अलग थ्रेड का उपयोग करना चाह सकते हैं, इस मामले में एक DoEvents की आवश्यकता नहीं होगी। आप can do this in VB6 (सरल नहीं)।

+0

वह वीबी 6 है, vb.net नहीं। – GSerg

+0

मुझे लगता है कि आप डाउनवॉटेड थे क्योंकि आपने कहा था कि वह "एक अलग थ्रेड का उपयोग करना बेहतर होगा"। – MusiGenesis

+0

सहमत, और तय। – TheSoftwareJedi

8

नहीं, आपको DoEvents का उपयोग करना होगा अन्यथा सभी UI, कीबोर्ड और टाइमर ईवेंट कतार में प्रतीक्षा में रहेंगे।

एकमात्र चीज जो आप कर सकते हैं वह हर 1000 पुनरावृत्तियों या इस तरह के लिए एक बार DoEvents को कॉल कर रही है।

+0

यदि आप जल्दी से रद्द करना चाहते हैं, तो आप प्रत्येक पुनरावृत्ति पर DoEvents को कॉल करना चाहते हैं। – MusiGenesis

4

आप इसे एक अलग थ्रेड पर शुरू कर सकते हैं, लेकिन वीबी 6 में यह शाही दर्द है। DoEvents काम करना चाहिए। यह एक हैक है, लेकिन फिर वीबी 6 (10 साल वीबी अनुभवी यहां बात कर रहा है, तो मुझे नीचे मत करो)।

+0

हम्म, मैंने कहा, लेकिन नीचे मतदान किया गया ... अच्छा ... – TheSoftwareJedi

+0

वीबी 6 में CreateThread का उपयोग करने से कुछ प्रभाव पड़ते हैं जो कुछ मामलों में विचार करने के लिए बहुत घातक हैं। यह किसी ऐसे राज्य में वीबी रनटाइम डालता है जहां आप इसकी अपेक्षा नहीं करते हैं तो यह क्रैश हो सकता है। तो मैं इसका उपयोग नहीं कर रहा हूँ। ठीक है, मैं हूं, लेकिन केवल फ्लाई-जेनरेटेड छोटे एएसएम प्रोसेस चलाने के लिए जो किसी भी रनटाइम funcs को कॉल नहीं करते हैं। – GSerg

+0

मुझे यह कहना चाहिए था "... लेकिन वीबी 6 में यह सबसे मजेदार चीज है जो आप संभवतः कर सकते हैं।" – MusiGenesis

4

क्वांटा में लंबे समय तक चलने वाले कार्य को विभाजित करें। इस तरह के कार्यों को अक्सर एक साधारण पाश द्वारा संचालित किया जाता है, इसलिए इसे 10, 100, 1000, इत्यादि में स्लाइस करें। टाइमर नियंत्रण का प्रयोग करें और हर बार जब यह आग का हिस्सा होता है और जब आप जाते हैं तो अपने राज्य को बचाते हैं। प्रारंभ करने के लिए, प्रारंभिक स्थिति सेट अप करें और टाइमर को सक्षम करें। पूरा होने पर, टाइमर को अक्षम करें और परिणामों को संसाधित करें।

आप प्रति क्वांटम कितना काम कर रहे हैं इसे बदलकर इसे "ट्यून" कर सकते हैं। टाइमर इवेंट हैंडलर में आप "रद्द करें" की जांच कर सकते हैं और आवश्यकतानुसार जल्दी बंद कर सकते हैं। आप वर्कलोड और टाइमर को एक पूर्ण घटना के साथ UserControl में बंडल करके इसे सभी neater बना सकते हैं।

+0

यहां एकमात्र परेशानी यह है कि आपको "रद्द करें" बटन को छोड़कर बाकी सब कुछ भी अक्षम करना होगा। +1 क्योंकि यह सीधे प्रश्न का उत्तर देता है, बिना किसी डिवाइसेज के रद्दीकरण की अनुमति देने का तरीका दिखाता है, और वीबी 6 में थ्रेडिंग (डरावनी!) के बिना ... – JeffK

4

यह मेरी आवश्यकता होने पर मेरे लिए अच्छा काम करता है। यह देखने के लिए जांच करता है कि उपयोगकर्ता ने लूप से बाहर निकलने के लिए एस्केप कुंजी दबा दी है या नहीं।

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

Option Explicit 

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer 

Private Sub Command1_Click() 
    Do 
     Label1.Caption = Now() 
     Label1.Refresh 
     If WasKeyPressed(vbKeyEscape) Then Exit Do 
    Loop 

    Label1.Caption = "Exited loop successfully" 

End Sub 

Function WasKeyPressed(ByVal plVirtualKey As Long) As Boolean 
    If (GetAsyncKeyState(plVirtualKey) And &H8000) Then WasKeyPressed = True 
End Function 

प्रलेखन यहाँ है:

http://msdn.microsoft.com/en-us/library/ms646301(VS.85).aspx

+1

नियंत्रण-रोकथाम भी विकास के दौरान महान काम करता है – rpetrich

4

संपादित यह turns out MSDN लेख से दोषपूर्ण है और तकनीक DOESN'T WORK :(

यहाँ .NET BackgroundWorker घटक का उपयोग पर एक लेख है वीबी 6 के भीतर से किसी अन्य धागे पर कार्य चलाने के लिए।

3

वीबी 6 में एसिंक्रोनस पृष्ठभूमि प्रसंस्करण के लिए यहां एक सुंदर मानक योजना है। (उदाहरण के लिए यह डैन ऐप्पलमैन के book और माइक्रोसॉफ्ट के वीबी 6 samples में है।) आप काम करने के लिए एक अलग ActiveX EXE बनाते हैं: इस तरह काम एक अलग प्रक्रिया में स्वचालित रूप से किसी अन्य थ्रेड पर होता है (जिसका अर्थ है कि आपको चिंता करने की ज़रूरत नहीं है चर को तंग कर दिया जा रहा है)।

  • वीबी 6 ActiveX EXE ऑब्जेक्ट को किसी ईवेंट को चेकक्यूइट डूस्टफ() का खुलासा करना चाहिए। यह एक ByRef बूलियन को छोड़ दिया जाता है।
  • क्लाइंट ActiveX EXE ऑब्जेक्ट में StartDoStuff को कॉल करता है। यह दिनचर्या एक छिपे हुए फॉर्म पर टाइमर शुरू करती है और तुरंत लौटाती है। यह कॉलिंग थ्रेड unblocks। टाइमर अंतराल बहुत छोटा है इसलिए टाइमर घटना जल्दी से आग लगती है।
  • टाइमर इवेंट हैंडलर टाइमर को अक्षम करता है, और उसके बाद ActiveX ऑब्जेक्ट DoStuff विधि में वापस कॉल करता है। यह लंबी प्रसंस्करण शुरू होता है।
  • समय-समय पर DoStuff विधि CheckQuitDoStuff ईवेंट उठाती है। क्लाइंट का इवेंट हैंडलर विशेष ध्वज की जांच करता है और अगर इसे निरस्त करना आवश्यक है तो सेट छोड़ें। फिर DoStuff गणना बंद कर देता है और अगर सही हो तो जल्दी से लौटता है।

इस योजना का अर्थ है कि क्लाइंट को वास्तव में बहु-थ्रेडेड होने की आवश्यकता नहीं है, क्योंकि कॉलिंग थ्रेड ब्लॉक नहीं होता है जबकि "DoStuff" हो रहा है। मुश्किल हिस्सा यह सुनिश्चित कर रहा है कि DoStuff घटनाओं को उचित अंतराल पर उठाता है - बहुत लंबा, और जब आप चाहें तो छोड़ नहीं सकते: बहुत छोटा, और आप DoStuff को अनावश्यक रूप से धीमा कर रहे हैं। साथ ही, जब DoStuff निकलता है, तो उसे छिपे हुए फॉर्म को अनलोड करना होगा।

यदि DoStuff वास्तव में निरस्त होने से पहले किए गए सभी सामानों को प्राप्त करने में कामयाब होता है, तो आप क्लाइंट को यह बताने के लिए एक अलग घटना उठा सकते हैं कि काम समाप्त हो गया है।

संबंधित मुद्दे