2012-04-13 5 views
7

में एक टाइमआउट कार्यान्वित करना मैं सी # के लिए नया हूं; मैंने मुख्य रूप से जावा किया है।सी #

मैं पंक्तियों के साथ एक टाइमआउट कुछ लागू करना चाहते हैं:

int now= Time.now(); 
while(true) 
{ 
    tryMethod(); 
    if(now > now+5000) throw new TimeoutException(); 
} 

मैं कैसे सी # में यह लागू कर सकते हैं? धन्यवाद!

+0

आप [स्टॉपवॉच] (http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx) वर्ग को देखने के लिए चाहता हूँ। [यहां] (http://stackoverflow.com/a/5019172/95573) एक उदाहरण है – SwDevMan81

+2

'tryMethod' क्या करता है? उपर्युक्त कोड में, आपका if कथन केवल 'trymethod' पूरा होने के बाद ही पहुंचा जाएगा। – JMK

+2

ऐसा लगता है कि आप असीमित रूप से निष्पादित करना चाहते हैं? – emd

उत्तर

25

एक संभव तरीका होगा

Stopwatch sw = new Stopwatch(); 
sw.Start(); 
while(true) 
{ 
    tryMethod(); 
    if(sw.ElapsedMilliseconds > 5000) throw new TimeoutException(); 
} 

हालांकि आप वर्तमान में किसी भी तरह अपनी लूप से बाहर तोड़ने के लिए है। मैं tryMethod एक बूलियन लौट सकते हैं और

Stopwatch sw = new Stopwatch(); 
sw.Start(); 
while(!tryMethod()) 
{ 
    if(sw.ElapsedMilliseconds > 5000) throw new TimeoutException(); 
} 
+2

के लिए त्वरित जांच है, जब दिन की रोशनी बचत दिनों की बात आती है – Servy

+1

@ सर्वी आप सही हैं, डेटटाइम के बजाय स्टॉपवॉच का उपयोग करने के लिए मेरा जवाब संपादित करें। –

+0

मुझे पूरा यकीन है कि ओपी tryMethod पर टाइमआउट ऑपरेशन करने में सक्षम होना चाहता है हालांकि – KingCronus

4

मुझे लगता है कि आप एक टाइमर और एक प्रतिनिधि के साथ ऐसा कर सकता है के लिए इसे बदल होने की सिफारिश करेंगे, मेरे उदाहरण कोड के नीचे है:

using System; 
using System.Timers; 

class Program 
{ 
    public delegate void tm(); 

    static void Main(string[] args) 
    { 
     var t = new tm(tryMethod); 
     var timer = new Timer(); 
     timer.Interval = 5000; 

     timer.Start(); 

     timer.Elapsed += (sender, e) => timer_Elapsed(t); 
     t.BeginInvoke(null, null); 
    } 

    static void timer_Elapsed(tm p) 
    { 
     p.EndInvoke(null); 
     throw new TimeoutException(); 
    } 

    static void tryMethod() 
    { 
     Console.WriteLine("FooBar"); 
    } 
} 

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

+0

मुझे लगता है कि यह ओपी के विपरीत क्या है - यह कोड सुनिश्चित करता है कि विधि कम से कम 5000ms के लिए समाप्त नहीं होती है, ऐसा लगता है कि ओपी 5000ms पर बार-बार एक विधि को चलाने के लिए चाहता है। –

+0

आह क्षमा चाहते हैं, मुझे यह पीछे की ओर मिला! – JMK

+0

अन्य उत्तर (जबकि लूप संस्करण) ब्लॉकिंग ऑपरेशन के साथ काम नहीं कर रहा है। मैं कुछ परीक्षण करूँगा, लेकिन अभी पूछ रहा हूं, क्या यह टाइमर अवरुद्ध करने के लिए काम करेगा? – liang

2

जब तक tryMethod() इस ब्लॉक नहीं करता, जैसा कि आप क्या चाहते हैं करना चाहिए:

डेलाइट सेविंग टाइम के लिए सुरक्षित या समय क्षेत्रों को बदलने नहीं जब मोबाइल:

DateTime startTime = DateTime.Now; 

while(true) 
{ 
    tryMethod(); 
    if(DateTime.Now.Subtract(startTime).TotalMilliseconds > 5000) 
     throw new TimeoutException(); 
} 

समय-क्षेत्र और डेलाइट सेविंग टाइम सुरक्षित संस्करणों:

DateTime startTime = DateTime.UtcNow; 

while(true) 
{ 
    tryMethod(); 
    if(DateTime.UtcNow.Subtract(startTime).TotalMilliseconds > 5000) 
     throw new TimeoutException(); 
} 

(। .NET 3.5 या DateTimeOffset के लिए आवश्यक अधिक)

DateTimeOffset startTime = DateTimeOffset.Now; 

while(true) 
{ 
    tryMethod(); 
    if(DateTimeOffset.Now.Subtract(startTime).TotalMilliseconds > 5000) 
     throw new TimeoutException(); 
} 
+0

अलग-अलग समय क्षेत्रों को ध्यान में रखने के लिए डेटटाइम को सार्वभौमिक समय में परिवर्तित करना बेहतर है? अगर मैं UtcNow का उपयोग करता हूं तो क्या इससे कोई फर्क पड़ता है? –

+0

@ सिंपलफेलो इस टाइमज़ोन और डेलाइट बचत समय को सुरक्षित करने के दो तरीके हैं। अद्यतन उत्तर देखें। UtcNow का उपयोग कनवर्ट करने से बेहतर है क्योंकि रूपांतरण को तब भी किया जा सकता है जब रूपांतरण किया जाता है। – JamieSee

0

एक और तरीका है कि मैं यह करना पसंद:

public class TimeoutAction 
    { 
     private Thread ActionThread { get; set; } 
     private Thread TimeoutThread { get; set; } 
     private AutoResetEvent ThreadSynchronizer { get; set; } 
     private bool _success; 
     private bool _timout; 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="waitLimit">in ms</param> 
     /// <param name="action">delegate action</param> 
     public TimeoutAction(int waitLimit, Action action) 
     { 
      ThreadSynchronizer = new AutoResetEvent(false); 
      ActionThread = new Thread(new ThreadStart(delegate 
      { 
       action.Invoke(); 
       if (_timout) return; 
       _timout = true; 
       _success = true; 
       ThreadSynchronizer.Set(); 
      })); 

      TimeoutThread = new Thread(new ThreadStart(delegate 
      { 
       Thread.Sleep(waitLimit); 
       if (_success) return; 
       _timout = true; 
       _success = false; 
       ThreadSynchronizer.Set(); 
      })); 
     } 

     /// <summary> 
     /// If the action takes longer than the wait limit, this will throw a TimeoutException 
     /// </summary> 
     public void Start() 
     { 
      ActionThread.Start(); 
      TimeoutThread.Start(); 

      ThreadSynchronizer.WaitOne(); 

      if (!_success) 
      { 
       throw new TimeoutException(); 
      } 
      ThreadSynchronizer.Close(); 
     } 
    } 
1

Async विधि पर कस्टम समय समाप्ति के लिए कार्य का उपयोग करना

यहाँ एक विधि के साथ एक कस्टम वर्ग की मेरी कार्यान्वयन एक कार्य रैप करने के लिए समय समाप्त करने के लिए ।

public class TaskWithTimeoutWrapper 
{ 
    protected volatile bool taskFinished = false; 

    public async Task<T> RunWithCustomTimeoutAsync<T>(int millisecondsToTimeout, Func<Task<T>> taskFunc, CancellationTokenSource cancellationTokenSource = null) 
    { 
     this.taskFinished = false; 

     var results = await Task.WhenAll<T>(new List<Task<T>> 
     { 
      this.RunTaskFuncWrappedAsync<T>(taskFunc), 
      this.DelayToTimeoutAsync<T>(millisecondsToTimeout, cancellationTokenSource) 
     }); 

     return results[0]; 
    } 

    public async Task RunWithCustomTimeoutAsync(int millisecondsToTimeout, Func<Task> taskFunc, CancellationTokenSource cancellationTokenSource = null) 
    { 
     this.taskFinished = false; 

     await Task.WhenAll(new List<Task> 
     { 
      this.RunTaskFuncWrappedAsync(taskFunc), 
      this.DelayToTimeoutAsync(millisecondsToTimeout, cancellationTokenSource) 
     }); 
    } 

    protected async Task DelayToTimeoutAsync(int millisecondsToTimeout, CancellationTokenSource cancellationTokenSource) 
    { 
     await Task.Delay(millisecondsToTimeout); 

     this.ActionOnTimeout(cancellationTokenSource); 
    } 

    protected async Task<T> DelayToTimeoutAsync<T>(int millisecondsToTimeout, CancellationTokenSource cancellationTokenSource) 
    { 
     await this.DelayToTimeoutAsync(millisecondsToTimeout, cancellationTokenSource); 

     return default(T); 
    } 

    protected virtual void ActionOnTimeout(CancellationTokenSource cancellationTokenSource) 
    { 
     if (!this.taskFinished) 
     { 
      cancellationTokenSource?.Cancel(); 
      throw new NoInternetException(); 
     } 
    } 

    protected async Task RunTaskFuncWrappedAsync(Func<Task> taskFunc) 
    { 
     await taskFunc.Invoke(); 

     this.taskFinished = true; 
    } 

    protected async Task<T> RunTaskFuncWrappedAsync<T>(Func<Task<T>> taskFunc) 
    { 
     var result = await taskFunc.Invoke(); 

     this.taskFinished = true; 

     return result; 
    } 
} 

तो फिर तुम इसे इस तरह कॉल कर सकते हैं:

await new TaskWithTimeoutWrapper().RunWithCustomTimeoutAsync(10000,() => this.MyTask()); 

या

var myResult = await new TaskWithTimeoutWrapper().RunWithCustomTimeoutAsync(10000,() => this.MyTaskThatReturnsMyResult()); 

और आप एक रद्द टोकन जोड़ सकते हैं अगर आप अगर यह करने के लिए हो जाता है चल रहा async कार्य रद्द करना चाहते हैं समय समाप्त।

आशा है कि यह मदद करता है

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

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