2012-07-05 20 views
10

में विशिष्ट समय के बाद पाश मैं अपने प्रोजेक्ट (सी #, VS2010, .NET 4.0) है कि एक विशेष for पाश 200 मिलीसेकेंड के भीतर समाप्त करना चाहिए में एक आवश्यकता है। यदि ऐसा नहीं होता है तो शेष अवधि को निष्पादित किए बिना इस अवधि के बाद इसे समाप्त करना होगा। लूप आमतौर पर i = 0 के लिए लगभग 500,000 से 700,000 तक जाता है, इसलिए कुल लूप समय भिन्न होता है।बाहर निकलें सी #

मैं निम्नलिखित प्रश्न जो समान हैं पढ़ा है, लेकिन वे मेरे मामले में मदद नहीं की:

  1. What is the best way to exit out of a loop after an elapsed time of 30ms in C++
  2. How to execute the loop for specific time

अब तक मैं ट्रैक करने के लिए एक Stopwatch वस्तु का उपयोग कर की कोशिश की है विलुप्त समय लेकिन यह मेरे लिए काम नहीं कर रहा है।

विधि 1.for पाश के भीतर बीता हुआ समय की तुलना करना:: यहाँ 2 अलग अलग तरीकों मैं अब तक की कोशिश की है कर रहे हैं

Stopwatch sw = new Stopwatch(); 
sw.Start(); 

for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000 
{ 
     // Do some stuff 
     ... 
     ... 
     ... 

     if (sw.Elapsed > TimeSpan.FromMilliseconds(200)) 
      break; 
} 

sw.Stop(); 

यह काम नहीं करता क्योंकि if (sw.Elapsed > TimeSpan.FromMilliseconds(200)) पूरा करने के लिए 200 से अधिक मिलीसेकेंड लेता है। इसलिए मेरे मामले में बेकार। मुझे यकीन नहीं है कि TimeSpan.FromMilliseconds() आमतौर पर यह लंबा लगता है या यह किसी कारण से मेरे मामले में है।

विधि 2. समय की तुलना करने के एक अलग थ्रेड बनाना:

Stopwatch sw = new Stopwatch(); 
sw.Start();      
bool bDoExit = false; 
int msLimit = 200; 

System.Threading.ThreadPool.QueueUserWorkItem((x) => 
{ 
    while (bDoExit == false) 
    { 
     if (sw.Elapsed.Milliseconds > msLimit) 
     { 
      bDoExit = true; 
      sw.Stop(); 
     } 

     System.Threading.Thread.Sleep(10); 
     } 

}); 

for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000 
{ 
     // Do some stuff 
     ... 
     ... 
     ... 

     if (bDoExit == true) 
      break; 
} 

sw.Stop(); 

मैं में कुछ अन्य कोड है पाश है कि कुछ आंकड़े प्रिंट के लिए। यह मुझे बताता है कि विधि 2 के मामले में, for लूप निश्चित रूप से सभी पुनरावृत्तियों को पूरा करने से पहले टूट जाता है लेकिन लूप समय अभी भी 280-300 मिलीसेकंड है।

200 मिलीसेकंड या उससे कम के साथ सख्ती से लूप को तोड़ने के लिए कोई सुझाव? धन्यवाद।

+0

उस लूप को चलाने वाले थ्रेड को मारने के बारे में कैसे? यद्यपि आदर्श नहीं हो सकता है। –

+0

http://stackoverflow.com/questions/5945533/how-to-execute-the-loop-for- विशिष्ट- समय – akhil

+0

@ फिलिप एकबर्ग, अच्छा बिंदु! इसे ठीक करने की आवश्यकता है। :) हालांकि यह मेरी समस्या को ठीक करने में मेरी मदद नहीं कर सकता है। हालांकि यह एक अच्छा अभ्यास है। धन्यवाद। – silverspoon

उत्तर

5

एक तेजी से तुलना के लिए

if(sw.ElapsedMilliseconds > 200) 
    break; 

की तुलना की कोशिश आप अपने पाश की शुरुआत में उस चेक करते हैं और प्रसंस्करण के दौरान भी चाहिए, ("// कुछ सामान है" कोड का हिस्सा), क्योंकि यह है उदाहरण के लिए, यह प्रसंस्करण 1 9 0 (लूप की शुरुआत) से शुरू होता है, 20 रहता है और 210 पर समाप्त होता है।

आप अपने प्रसंस्करण के औसत निष्पादन समय को भी माप सकते हैं (यह अनुमानित है क्योंकि यह औसत समय पर निर्भर करता है), इस तरह लूप को 200 मिलीसेकंड या उससे कम समय तक चलना चाहिए, यहां एक डेमो है जिसे आप मुख्य विधि में डाल सकते हैं कंसोल आवेदन और आसानी से अपने आवेदन के लिए इसे संशोधित:

 Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     string a = String.Empty; 
     int i; 
     decimal sum = 0, avg = 0, beginning = 0, end = 0; 
     for (i = 0; i < 700000; i++) // nEntries is typically more than 500,000 
     { 
      beginning = sw.ElapsedMilliseconds; 
      if (sw.ElapsedMilliseconds + avg > 200) 
       break; 

      // Some processing 
      a += "x"; 
      int s = a.Length * 100; 
      Thread.Sleep(19); 
      ///////////// 

      end = sw.ElapsedMilliseconds; 
      sum += end - beginning; 
      avg = sum/(i + 1); 

     } 
     sw.Stop(); 

     Console.WriteLine(
      "avg:{0}, count:{1}, milliseconds elapsed:{2}", avg, i + 1, 
      sw.ElapsedMilliseconds); 
     Console.ReadKey(); 
+0

एकाधिक स्थानों पर समय की जांच करना एक अच्छा विचार है। मेरा कोड अब "बेहतर (sw.ElapsedMilliseconds> 200)" के साथ बहुत बेहतर व्यवहार करता है। धन्यवाद। और हाँ, मैं पहले से ही प्रति लूप औसत समय मापता हूं। – silverspoon

+0

मैंने 'sw.ElapsedMilliseconds' बिट जोड़ने के बाद बस अपने आवेदन का परीक्षण समाप्त कर दिया। भले ही मैं निर्दिष्ट समय के भीतर लूप को तोड़ने में सक्षम हूं, परिणाम मेरे पिछले अवलोकनों के समान ही हैं - sw.ElapsedMilliseconds की गणना करने में लंबा समय लगता है। इसलिए यदि मैं लूप को 'sw.ElapsedMilliseconds' का उपयोग करने के बाद तोड़ने के बिना जारी रखता हूं तो कुल लूप समय लगभग 3 सेकंड (280-300ms के बजाय) होता है। बहुत अजीब। – silverspoon

+0

2 मामलों के साथ ब्रेक स्टेटमेंट के बिना लूप का परीक्षण करने का प्रयास करें: पहले मामले में '(sw.ElapsedMilliseconds + avg> 200) तोड़ने के बजाय; 'उपयोग' (sw.ElapsedMilliseconds + avg> 200) {} 'और दूसरे मामले में टिप्पणी में की तरह बाहर ElapsedMilliseconds comparsion इस '//(sw.ElapsedMilliseconds + औसत> 200) {}', दो मामलों के बीच समय अंतर समय भूमि के ऊपर है कि ElapsedMilliseconds comparsion (रों) से जोड़ा जाता है। –

1

पहले एक का उपयोग करें - सरल और दूसरे की तुलना में सटीक होने की बेहतर संभावनाएं हैं।

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

TimeSpan.FromMilliseconds(200) के लिए कोई महत्वपूर्ण समय लेने के लिए बिल्कुल कोई कारण नहीं है (साथ ही इसे प्रत्येक पुनरावृत्ति में कॉल करना)।

+0

दूसरी विधि में भी 'बीडीओएक्सिट' तक पहुंचने पर आपको दौड़ की स्थिति होगी। इसके बजाय आप दूसरी विधि को दोबारा कर सकते हैं और रद्दीकरण टोकन (http://msdn.microsoft.com/en-us/library/dd997364.aspx) का उपयोग कर सकते हैं। वे रोकने के लिए _asking_ एक ऑपरेशन के लिए डिज़ाइन किए गए हैं। –

+0

@ जसद, मैं इसे दौड़ की स्थिति नहीं कहूंगा क्योंकि केवल एक लेखक है। कोड स्पष्ट रूप से 'अस्थिर' के बिना काम करने का अवसर नहीं है (क्योंकि इसे लूप में अनुकूलित किया जा सकता है ...), लेकिन अगर यह अंततः बूलियन वैरिएबल में परिवर्तन लेगा (क्योंकि यह केवल एक संक्रमण को झूठा बनाता है-> सच)। –

+0

आप सही हैं, दौड़ की स्थिति नहीं हो सकती क्योंकि एक बूलियन पढ़ने और लिखना एक परमाणु ऑपरेशन है। मेरी गलती। –

0

मैं अगर यह है कि वास्तव में नहीं पता है, लेकिन मुझे लगता है कि का उपयोग कर एक System.Timers.Timer एक कोशिश के लायक है:

int msLimit = 200; 
int nEntries = 500000; 
bool cancel = false; 

System.Timers.Timer t = new System.Timers.Timer(); 
t.Interval = msLimit; 
t.Elapsed += (s, e) => cancel = true; 
t.Start(); 

for (int i = 0; i < nEntries; i++) 
{ 
    // do sth 

    if (cancel) { 
     break; 
    } 
} 
1

एक अन्य विकल्प होगा CancellationTokenSo का उपयोग करने के लिए urce:

CancellationTokenSource source = new CancellationTokenSource(100); 

while(!source.IsCancellationRequested) 
{ 
    // Do stuff 
} 
संबंधित मुद्दे