2009-05-02 27 views
12

मेरे पास एक टाइमर है जिसे एक ही समय में अपने विलुप्त होने वाले ईवेंट हैंडलर को संसाधित करने की आवश्यकता नहीं है। लेकिन एक विलुप्त घटना प्रसंस्करण दूसरों के साथ हस्तक्षेप कर सकता है। मैंने नीचे दिए गए समाधान को लागू किया, लेकिन कुछ गलत लगता है; ऐसा लगता है कि मुझे टाइमर का अलग-अलग उपयोग करना चाहिए या थ्रेडिंग स्पेस के भीतर किसी अन्य ऑब्जेक्ट का उपयोग करना चाहिए। टाइमर सबसे अच्छा लग रहा था क्योंकि मुझे समय-समय पर स्थिति की जांच करने की आवश्यकता होती है, लेकिन कभी-कभी जांच मेरे अंतराल से अधिक समय लेती है। क्या यह इस तक पहुंचने का सबसे अच्छा तरीका है?विलुप्त घटना को संसाधित करते समय टाइमर को कैसे अवरुद्ध करें?

// member variable 
private static readonly object timerLock = new object(); 
private bool found = false; 


// elsewhere 
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds; 
timer.Elapsed = Timer_OnElapsed; 
timer.Start(); 


public void Timer_OnElapsed(object sender, ElapsedEventArgs e) 
{ 
    lock(timerLock) 
    { 
    if (!found) 
    { 
     found = LookForItWhichMightTakeALongTime(); 
    } 
    } 
} 
+2

यह एक समुदाय विकी नहीं होना चाहिए था। – Samuel

+0

@ सैमुएल - यदि कोई पोस्टर चाहता है तो कोई प्रश्न समुदाय विकी हो सकता है। एफएक्यू केवल निर्दिष्ट करता है कि कुछ प्रश्न शुरुआत से सामुदायिक विकी होना चाहिए, लेकिन सीडब्लू को किसी भी प्रश्न पर लागू नहीं करना चाहिए। – tvanfosson

+1

@tvanfosson: मैं उसे बता रहा था कि इस तरह के प्रश्न समुदाय विकी नहीं होना चाहिए। – Samuel

उत्तर

13

आप ऑटोरसेट को झूठी पर सेट कर सकते हैं, फिर इसे संभालने के बाद टाइमर को स्पष्ट रूप से रीसेट कर दें। बेशक, आप इसे कैसे संभालेंगे वास्तव में इस बात पर निर्भर करता है कि आप टाइमर को कैसे संचालित करते हैं। ऐसा करने से यह आपके टाइमर को वास्तविक निर्दिष्ट अंतराल से दूर जाने की अनुमति देगा (जैसे रोकना और पुनरारंभ करना)। आपका तंत्र प्रत्येक अंतराल को आग लगने और संभालने की अनुमति देगा, लेकिन इसके परिणामस्वरूप अनचाहे घटनाओं का बैकलॉग हो सकता है जो अब संभाला जाता है जहां टाइमर की समाप्ति के पास हैंडलर का आह्वान होता है।

timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds; 
timer.Elapsed += Timer_OnElapsed; 
timer.AutoReset = false; 
timer.Start(); 


public void Timer_OnElapsed(object sender, ElapsedEventArgs e) 
{ 
    if (!found) 
    { 
     found = LookForItWhichMightTakeALongTime(); 
    } 
    timer.Start(); 
} 
+0

ऑटोरसेट और विलुप्त सिस्टम के लिए हैं। थ्रेडिंग। टिमर जो यूआई काम के लिए सुरक्षित नहीं है। – Samuel

+0

@ सैमुएल - एक्सपैड वह घटना है जिसे ओपी उपयोग कर रहा है। संभवतः यह WinForms ऐप नहीं है। – tvanfosson

8

मैं आमतौर पर टाइमर रोक जबकि यह प्रसंस्करण, एक कोशिश/अंत में ब्लॉक दर्ज करें, और जब किया टाइमर को फिर से शुरू।

0
timer.enabled = false 

या

timer.stop(); 

और

timer.enabled = true 

या

timer.start(); 
-1

मैं इतना

तरह System.Threading.Timer का उपयोग 10
class Class1 
    { 
     static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1)); 

     private static void DoSomething(object state) 
     { 
      timer = null; // stop timer 

      // do some long stuff here 

      timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); 
     } 



    } 
+1

जब आप ' –

+0

के साथ किए जाते हैं तो आपको हमेशा टाइमर के उदाहरणों का निपटान करना चाहिए जब तक कि कचरा कलेक्टर इसे साफ़ नहीं कर लेता है, टाइमर कॉलबैक विधि को फायरिंग करेगा।इससे अप्रत्याशित, गैर-निर्धारिती प्रभाव हो सकते हैं। –

1

LookForItWhichMightTakeALongTime() एक लंबे समय लेने के लिए जा रहा है, तो मैं एक System.Windows.Forms.Timer का उपयोग नहीं क्योंकि ऐसा करने से आपके यूआई धागा बंद जाएगा और उपयोगकर्ता अपने आवेदन यह सोच कर कि यह जम गया है को मार सकता है सुझाव है।

आप क्या उपयोग कर सकते हैं BackgroundWorker (Timer के साथ यदि वांछित है)।

public class MyForm : Form 
{ 
    private BackgroundWorker backgroundWorker = new BackgroundWorker(); 

    public MyForm() 
    { 
    InitializeComponents(); 
    backgroundWorker.DoWork += backgroundWorker_DoWork; 
    backgroundWorker.RunWorkerCompleted += 
           backgroundWorker_RunWorkerCompleted; 
    backgroundWorker.RunWorkerAsync(); 
    } 

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
    e.Result = LookForItWhichMightTakeALongTime(); 
    } 

    private void backgroundWorker_RunWorkerCompleted(object sender, 
              RunWorkerCompletedEventArgs e) 
    { 
    found = e.Result as MyClass; 
    } 
} 

और तुम भी, कहीं भी आप करना चाहते हैं से RunWorkerAsync() कॉल कर सकते हैं एक Timer से भले ही आप चाहते हैं। और यह सुनिश्चित करना सुनिश्चित करें कि BackgroundWorkerRunWorkerAsync() को कॉल करते समय पहले से चल रहा है, जब यह चल रहा है तो अपवाद फेंक देगा।

private void timer_Tick(object sender, EventArgs e) 
{ 
    if (!backgroundWorker.IsBusy) 
    backgroundWorker.RunWorkerAsync(); 
} 
संबंधित मुद्दे