2011-01-25 34 views
6

मेरे विंडोज सेवा ऐप में मैं टाइमर का उपयोग कर रहा हूं। मैं केवल सिस्टम का उपयोग कर रहा हूँ। टाइमर। मैंने पहले इस समस्या का सामना करना कभी नहीं किया है, लेकिन अचानक मैं इस अपवाद है:.NET 3.5 C# सिस्टम के साथ बग। टाइमर सिस्टम। ऑब्जेक्ट डिस्प्ले अपवाद: एक डिस्पोजेड ऑब्जेक्ट का उपयोग नहीं कर सकता

System.ObjectDisposedException: Cannot access a disposed object. 
    at System.Threading.TimerBase.ChangeTimer(UInt32 dueTime, UInt32 period) 
    at System.Threading.Timer.Change(Int32 dueTime, Int32 period) 
    at System.Timers.Timer.UpdateTimer() 
    at System.Timers.Timer.set_Interval(Double value) 
    at MyApp.MySpace.MySpace2.MyClassWithTimer.MethodChangeTimerInterval() 

मेरी विधि में मैं टाइमर रोक रहा हूँ, और टाइमर अंतराल बदल रहा है। यही वह जगह है जहां मुझे अपवाद मिला।

मैंने इस बग के बारे में कुछ पढ़ा है लेकिन क्या यह अभी भी यह बग है .NET 3.5 में भी?

मैं इसे कैसे ठीक करूं? क्या मुझे एक नई वस्तु को अंतराल को रोकने और सेट करने के बाद टाइमर ऑब्जेक्ट को नवीनीकृत करना चाहिए? मैं जीसी.किपलाइव (डेटा टाइमर) का उपयोग कर रहा हूं;

संपादित करें:

* मैं एक लिंक http://www.kbalertz.com/kb_842793.aspx असल में जैसे ही आप एक टाइमर रोक के रूप में पाया, आंतरिक System.Threading.Timer के लिए उपलब्ध हो जाता है: मैं इस समस्या के बारे में कुछ अन्य प्रश्न पाया कचरा संग्रह, कभी-कभी समाप्त होने वाली घटना नहीं होती है, या कभी-कभी एक डिस्पोजेड संदर्भ अपवाद उत्पन्न करती है। हालांकि लेख में वर्णित नहीं है, मेरा समाधान था जब टाइमर को हर बार एक नया टाइमर बनाने के लिए रोक दिया गया था और समाप्त हो गए ईवेंट को दोबारा जोड़ दिया गया था। कुशल लेकिन आसान नहीं, और मेरे लिए प्रोसेसर-वार समस्या नहीं है। इसने मेरी समस्या पूरी तरह हल कर ली है। सभी जो जवाब दिया के लिए चीयर्स। *

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

कोड है कि

private void StartAsyncResponseTimer() 
{ 
    switch (_lastRequestType) 
    { 
     case 1: 
      asyncResponseTimer.Interval = 1000; 
      break; 
     case 2: 
      asyncResponseTimer.Interval = 2000; 
      break; 
     case 3: 
      asyncResponseTimer.Interval = 3000; 
      break; 
     default: 
      asyncResponseTimer.Interval = 10000; 
      break; 
    } 

    asyncResponseTimer.Start(); 
} 

समारोह SerialPortDataReceived घटना से बुलाया गया था:

private void SerialPortDataReceived(object sender, EventArgs e) 
{ 
     StartAsyncResponseTimer(); 
} 

टाइमर बदलते अंतराल कॉल करने से पहले बंद कर दिया गया था त्रुटि के कारण।

private Timer asyncResponseTimer = new Timer(); 

संपादित करें:

टाइमर मेरी कक्षा का निजी क्षेत्र है आवेदन एक पंक्ति में कई महीनों के लिए चल रहा है और यह पहली बार मैं इस अपवाद मिल गया है!

मेरे निपटाने पैटर्न:

public class SerialPortCommunication{ 

... 

    private void SerialPortDataReceived(object sender, EventArgs e) 
    { 
     ReadResponse(); 

     StartAsyncResponseTimer(); 
    } 

    //used to determine if is recieving response over 
    private void StartAsyncResponseTimer() 
    { 
     switch (_lastRequestType) 
     { 
      case 1: 
       asyncResponseTimer.Interval = 1000; 
       break; 
      case 2: 
       asyncResponseTimer.Interval = 2000; 
       break; 
      case 3: 
       asyncResponseTimer.Interval = 3000; 
       break; 
      default: 
       asyncResponseTimer.Interval = 10000; 
       break; 
     } 

     asyncResponseTimer.Start(); 
    } 

    public virtual void Dispose() 
    { 

     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!this._disposed) 
     { 
      if (disposing) 
      { 
       // Dispose managed resources. 

      } 

      // Dispose unmanaged resources. 
      _disposed = true; 

      Stop(); 

     } 
    } 

    ~SomeClass() 
    { 

     Dispose(false); 
    } 

    #endregion 




    public void Stop() 
    { 
     _asyncResponseTimer.Stop(); 
     serialPortManager.ClosePort(); 
    } 
} 
+0

हमें अपने कोड के साथ ही त्रुटि संदेश दें - यह बहुत सहायक हो करने के लिए जब तक कि मैं कोड के कुछ और हिस्सों देख सकते हैं नहीं जा रहा है। मेरा अनुमान है कि आप "उपयोग" ब्लॉक का उपयोग कर रहे हैं जो समाप्त होने पर समाप्त होने पर कुछ ऑटो-डिस्पोजेक्ट करता है। हम आपका कोड देखेंगे और आपको बताने की कोशिश करेंगे। – Chris

+2

क्या (जैसे एक निजी क्षेत्र या टाइमर का संग्रह) ने अपने लायक मेरी तकनीक जब टाइमर का उपयोग कर कहीं आसपास उन्हें एक संदर्भ रखना है के लिए इतना है कि मैं जानता हूँ कि वहाँ अभी भी संदर्भ हैं। इस तरह से मुझे पता है कि वे जीसीड नहीं होने से पहले जीसीड नहीं होंगे। हालांकि आप निश्चित रूप से यह सुनिश्चित करना चाहते हैं कि आप टाइमर ऑब्जेक्ट के साथ किए जाने पर उस संदर्भ को हटा दें। – Chris

+0

मेरे पास कक्षा के निजी सदस्य के रूप में संदर्भित टाइमर है। – Simon

उत्तर

1

यह हो सकता है कि आपके सीरियल पोर्ट डेटा बस के बाद आप अपने टाइमर फेंक दिया हो रही? यह एकमात्र चीज है जो आपके दिमाग में आपके द्वारा पोस्ट किए गए डेटा के साथ आती है! स्टॉप() में आप क्या कर रहे हैं! निपटान के अंदर विधि() ????

+0

मैं फ़ंक्शन टाइमर को कभी भी कॉल नहीं कर रहा हूं।()। सीरियल पोर्ट संचार रोकने के लिए मुझे स्टॉप() की आवश्यकता है। मेरे पास विधि प्रारंभ() भी है। जब मैं कक्षा SerialPortCommunication का निपटान करता हूं, तो मैं निपटान के बाद होने वाली रोकने के लिए टाइमर को रोकता हूं, क्योंकि यह अलग-अलग धागे पर है। यह अपवाद निपटान पर उठाया नहीं गया था। यह धारावाहिक बंदरगाह के साथ संचार के बीच में खुशी है। टाइमर के अंतराल को रीसेट करना हर बार कहा जाता है जब SerialPortDataReceived() होता है। – Simon

+0

मेरे संपादन pls देखें। – Simon

1

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

आप उपरोक्त परिदृश्य पर विचार किया है? टाइमर ऑटो रीसेट है या नहीं? आप कब रोक रहे हैं()?

+0

टाइमर यह निर्धारित करने के लिए है कि कोई डेटा प्राप्त नहीं हुआ है या नहीं। तो टाइमर हर बार serialPortDataReceived होता है फिर से शुरू होता है। यदि टाइमर अपना काम पूरा करता है, तो मुझे पता चलेगा कि सभी डेटा प्राप्त हुए हैं और मैं अनुरोध भेजना जारी रख सकता हूं। टाइमर में डिफ़ॉल्ट AutoReset = true है। मैं केवल स्टॉप() को कॉल कर रहा हूं जब मैं धारावाहिक बंदरगाह संचार को रोकना चाहता हूं, और जब मुझे यह अपवाद मिला() को कॉल नहीं किया गया था। इसका मूल रूप से यूआई से उपयोगकर्ता द्वारा बुलाया जाता है। – Simon

1

चूंकि आपने अपना सर्वर कॉन्फ़िगरेशन निर्दिष्ट नहीं किया है, इसलिए मैं विंडोज सर्वर 2003 मान रहा हूं। जब आप इसका उल्लेख करते हैं कि यह लगभग दो महीने (लगभग) के लिए काम करता है, तो यह 49.7 days bug की याद दिलाता है। यह आपके परिदृश्य पर लागू नहीं हो सकता है, जब तक यह मार्च में फिर से दुर्घटनाग्रस्त न हो जाए। जो अच्छा है - :-)

Symptom 2
On a Windows Server 2003-based computer that is not running ISA Server, a similar problem occurs when the following conditions are true: You call the CreateTimerQueueTimer function repeatedly in an application. You set a specified period to trigger the timer that is created by the CreateTimerQueueTimer function.

The application runs for more than 49.7 days. After 49.7 days, the timer is triggered immediately instead of being triggered after the specified period. After several minutes, the timer is triggered correctly.

KeepAlive() यहाँ उपयोगी है क्योंकि आप श्रेणी स्तर पर टाइमर घोषित नहीं है। अंतराल को बदलने के लिए टाइमर को रोकना जरूरी नहीं है।

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

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