2008-08-27 14 views
28

एक VB.NET WinForms परियोजना में मैं एक अपवाद मिलएक डिस्पोजेड ऑब्जेक्ट तक नहीं पहुंच सकता - कैसे ठीक करें?

जब एक रूप को बंद करने के लिए एक निपटाए वस्तु

तक नहीं पहुंच सकता। यह बहुत ही कम होता है और मैं इसे मांग पर फिर से नहीं बना सकता। स्टैक ट्रेस इस तरह दिखता है:

Cannot access a disposed object. Object name: 'dbiSchedule'. 
    at System.Windows.Forms.Control.CreateHandle() 
    at System.Windows.Forms.Control.get_Handle() 
    at System.Windows.Forms.Control.PointToScreen(Point p) 
    at Dbi.WinControl.Schedule.dbiSchedule.a(Boolean A_0) 
    at Dbi.WinControl.Schedule.dbiSchedule.a(Object A_0, EventArgs A_1) 
    at System.Windows.Forms.Timer.OnTick(EventArgs e) 
    at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

डीबीआईशेड्यूल डीबीआई-टेक से शेड्यूल नियंत्रण है। फॉर्म पर एक टाइमर है जो हर कुछ मिनट में स्क्रीन पर शेड्यूल अपडेट करता है।

कोई विचार क्या अपवाद पैदा कर रहा है और मैं इसे ठीक करने के बारे में कैसे जा सकता हूं? या यहां तक ​​कि मांग पर इसे फिर से बनाने में सक्षम होने के नाते?


हेज! सारे सवालों के जवाब देने के लिए धन्यवाद। हम टाइमर को फॉर्मक्लोजिंग ईवेंट पर रोकते हैं और हम टाइमर टिक ईवेंट में इसका उपयोग करने से पहले शेड्यूल घटक पर IsDisposed प्रॉपर्टी की जांच करते हैं लेकिन इससे मदद नहीं मिलती है।

यह वास्तव में कष्टप्रद समस्या है क्योंकि अगर कोई ऐसे समाधान के साथ आया है जो काम करता है - मैं समाधान की पुष्टि करने में सक्षम नहीं हूं क्योंकि मैं मैन्युअल रूप से समस्या को पुन: उत्पन्न नहीं कर सकता।

उत्तर

19

नियंत्रण तक पहुंचने से पहले IsDisposed संपत्ति की जांच करने का प्रयास करें। आप इसे FormClosing ईवेंट पर भी देख सकते हैं, मानते हैं कि आप फॉर्मक्लोज्ड ईवेंट का उपयोग कर रहे हैं।

हम FormClosing घटना पर टाइमर रोक करते हैं और हम टाइमर टिक घटना में उपयोग करने से पहले अनुसूची घटक पर IsDisposed संपत्ति की जांच करना है लेकिन यह मदद नहीं करता है।

जीसी को कॉल करना IsDisposed की जांच करने से पहले चयन करें, लेकिन इससे सावधान रहें। रिको मारियानी द्वारा इस आलेख को पढ़ें "When to call GC.Collect()"।

1

क्या आप सुनिश्चित करते हैं कि टाइमर किसी भी तरह से 'डीबीएसड्यूड्यूल' को बाहर नहीं कर रहा है और 'डीबीएसशेड्यूल' का निपटान करने के बाद गोलीबारी की जा रही है?

यदि ऐसा होता है तो टाइमर अधिक तेजी से आग लगने पर आप इसे अधिक बार फिर से बनाने में सक्षम हो सकते हैं, इस प्रकार टाइमर फायरिंग के रूप में फॉर्म को बंद करने की संभावना बढ़ जाती है।

0

त्रुटि स्टैक ट्रेस को देखते हुए, ऐसा लगता है कि आपका टाइमर अभी भी सक्रिय है। प्रपत्र (i.e. फ़ॉर्म को ऑनक्लोज़() विधि में बंद करने पर टाइमर को रद्द करने का प्रयास करें। यह सबसे साफ समाधान की तरह दिखता है।

10

एक थ्रेडिंग समस्या की तरह दिखता है।
हाइपोथिसिस: हो सकता है कि आपके पास मुख्य नियंत्रण और टाइमर थ्रेड इस नियंत्रण तक पहुंच सके। मुख्य धागा बंद हो जाता है - कॉलिंग कंट्रोल। डिस्प्ले() यह इंगित करने के लिए कि मुझे इस नियंत्रण के साथ किया गया है और मैं इसे और अधिक कॉल नहीं करूंगा। हालांकि टाइमर थ्रेड अभी भी सक्रिय है - उस धागे पर संदर्भ स्विच, जहां यह उसी नियंत्रण पर विधियों को कॉल कर सकता है। अब नियंत्रण कहता है कि मैं विघटित हूं (पहले से ही मेरे संसाधनों को छोड़ दिया है) और मैं अब और काम नहीं करूँगा। ऑब्जेक्ट डिस्प्ले अपवाद।

इस हल करने के लिए कैसे: टाइमर धागा में, नियंत्रण पर फोन कर के तरीकों/गुण से पहले,

if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods 

के साथ एक चेक करना या वस्तु के निपटान से पहले टाइमर धागा बंद करो।

+11

IsDisposed की जांच करना कम हो जाएगा, लेकिन समस्या को खत्म नहीं करेगा। सही समाधान फॉर्म को बंद करने से पहले टाइमर को रोकना है। –

1

एक और स्थान जो आप टाइमर को रोक सकते हैं FormClosing ईवेंट है - यह वास्तव में बंद होने से पहले होता है, इसलिए अनुपलब्ध संसाधनों तक पहुंचने से पहले चीजों को रोकने के लिए यह एक अच्छी जगह है।

2

हम इसे टाइमर टिक घटना में उपयोग करने से पहले अनुसूची घटक पर IsDisposed संपत्ति जाँच करते हैं, लेकिन यह नहीं मदद करता है।

अगर मैं उस स्टैक ट्रेस को समझता हूं, तो यह आपका टाइमर नहीं है जो समस्या है, यह नियंत्रण में ही एक है - यह हो सकता है कि वे ठीक से सफाई न करें।

क्या आप स्पष्ट रूप से अपने नियंत्रण पर निपटान कर रहे हैं?

2

टाइमर को रोकने का मतलब यह नहीं है कि टाइमर को रोकने के दौरान इसे फिर से नहीं कहा जाएगा, टाइमर_टिक अभी भी फॉर्म के लिए संदेश लूप पर कतारबद्ध हो सकता है। क्या होगा कि आपको एक और टिक मिलेगी जिसकी आप उम्मीद नहीं कर रहे हैं। आप अपने टाइमर_टिक में क्या कर सकते हैं, टाइमर_Tick विधि को निष्पादित करने से पहले अपने टाइमर की सक्षम संपत्ति की जांच करें।

1

यदि यह sporadically होता है तो मेरा अनुमान है कि यह टाइमर के साथ कुछ करने के लिए है।

मैं अनुमान लगा रहा हूं (और यह केवल एक अनुमान है क्योंकि मेरे पास आपके कोड तक कोई पहुंच नहीं है) कि फॉर्म बंद होने पर टाइमर फायरिंग कर रहा है। DbiSchedule ऑब्जेक्ट का निपटारा किया गया है लेकिन टाइमर किसी भी तरह से इसे कॉल करने का प्रयास करने के लिए अभी भी प्रबंधित करता है। यह नहीं होना चाहिए, क्योंकि यदि टाइमर के पास शेड्यूल ऑब्जेक्ट का संदर्भ है तो कचरा कलेक्टर इसे देखना चाहिए और इसका निपटान नहीं करना चाहिए।

यह मुझे पूछने के लिए प्रेरित करता है: क्या आप शेड्यूल ऑब्जेक्ट पर मैन्युअल रूप से निपटान() को कॉल कर रहे हैं? यदि हां, तो क्या आप टाइमर का निपटान करने से पहले ऐसा कर रहे हैं? सुनिश्चित करें कि आप इसे निपटाने से पहले शेड्यूल ऑब्जेक्ट के सभी संदर्भ जारी करते हैं (यानी पहले टाइमर का निपटान)।

अब मुझे एहसास है कि आपके द्वारा पोस्ट किए जाने के दौरान कुछ महीने बीत चुके हैं और जब मैं जवाब दे रहा हूं, तो उम्मीद है कि आपने इस मुद्दे को हल कर लिया है। मैं इसे दूसरों के लाभ के लिए लिख रहा हूं जो बाद में इसी तरह के मुद्दे के साथ आ सकते हैं।

उम्मीद है कि इससे मदद मिलती है।

2

मुझे एक ही समस्या थी और इसे एक बुलियन ध्वज का उपयोग करके हल किया गया जो फॉर्म बंद होने पर सेट हो जाता है (System.Timers.Timer में एक IsDisposed संपत्ति नहीं है)। फॉर्म पर हर जगह मैं टाइमर शुरू कर रहा था, मैंने यह ध्वज देखा था। अगर यह सेट किया गया था, तो टाइमर शुरू मत करो।

कारण::

मैं रोक दिया गया था और फार्म समापन समारोह में टाइमर के निपटान यहाँ कारण नहीं है। मैं timer_Elapsed() घटना में टाइमर शुरू कर रहा था। अगर मैं Timer_Elapsed() ईवेंट के बीच में फॉर्म को बंद करना चाहता था, तो टाइमर तुरंत Form_Closing() ईवेंट द्वारा निपटाया जाएगा।यह Timer_Elapsed() घटना से पहले हो खत्म और अधिक महत्वपूर्ण होगा, इससे पहले कि यह कोड की इस पंक्ति को मिला: जैसे ही उस पंक्ति एक ObjectDisposedException (मार डाला गया था

_timer.Start() 

) त्रुटि आप का उल्लेख के साथ फेंक दिया जायेगा ।

समाधान:

Private Sub myForm_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing 
    ' set the form closing flag so the timer doesn't fire even after the form is closed. 
    _formIsClosing = True 
    _timer.Stop() 
    _timer.Dispose() 
End Sub 

यहाँ टाइमर बीत घटना है:,

Private Sub Timer_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _timer.Elapsed 
    ' Don't want the timer stepping on itself (ie. the time interval elapses before the first call is done processing) 
    _timer.Stop() 

    ' do work here 

    ' Only start the timer if the form is open. Without this check, the timer will run even if the form is closed. 
    If Not _formIsClosing Then 
     _timer.Interval = _refreshInterval 
     _timer.Start() ' ObjectDisposedException() is thrown here unless you check the _formIsClosing flag. 
    End If 
End Sub 

दिलचस्प बात यह है कि पता करने के लिए भले ही यह ObjectDisposedException जब टाइमर शुरू करने के लिए प्रयास कर फेंक, टाइमर फॉर्म बंद होने पर भी इसे चलाने के लिए शुरू हो जाएगा (थ्रेड केवल तब बंद हो जाएगा जब एप्लिकेशन बंद था)।

0

मेरे समाधान एक कोशिश पकड़ डाल करने के लिए किया गया था, & काम कर रहा है ठीक

कोशिश {
this.Invoke (नई eventhandler (DoUpdate)); }
पकड़ {}

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

  • कोई संबंधित समस्या नहीं^_^