2011-09-14 10 views
9

मुझे एक समस्या है। मैं एक बेंचमार्क लिख रहा हूं और मेरे पास 2 सेकंड में या ~ 5 मिनट के बाद (इनपुट डेटा के आधार पर) की तुलना में एक फ़ंक्शन है। और मैं उस फ़ंक्शन को रोकना चाहूंगा यदि इसे 3 सेकंड से अधिक समय तक निष्पादित किया गया है ...सी में एक फ़ंक्शन के निष्पादन समय को कैसे सीमित करें?

मैं इसे कैसे कर सकता हूं?

बहुत बहुत धन्यवाद!

+0

संभावित डुप्लिकेट http://stackoverflow.com/questions/5025509/how-to-estimate-method-execution-time – Reniuz

+0

हां, यह डुप्लिकेट है, बेंचमार्किंग उसी तरह से समाप्त होता है जैसे किसी अन्य थ्रेड स्टॉप हो जाता है। –

उत्तर

3

सबसे अच्छा तरीका है, एक उच्च प्रदर्शन काउंटर के साथ एक OS कॉलबैक का उपयोग करें, तो अपने धागा मारने अपने समारोह इसके निष्पादन समय अक्सर इसे रोकने के लिए यह बहुत समय लगता है तय करने के लिए पर्याप्त जांच कर सकते हैं कि हो सकता है।

यदि यह मामला नहीं है, तो फ़ंक्शन को एक अलग थ्रेड में चलाएं। आपके मुख्य धागे में 3 सेकंड टाइमर शुरू करें। जब टाइमर समाप्त हो जाता है, Thread.Abort() का उपयोग करके अलग थ्रेड को मार दें (बेशक जब तक कि फ़ंक्शन पहले से खत्म नहीं हो जाता)। फ़ंक्शन दस्तावेज़ों में नमूना कोड और उपयोग के पूर्वाग्रह देखें।

+0

वास्तव में यह बहुत आसान है। यदि आपको वास्तव में धागे को एक असभ्य तरीके से मारने की ज़रूरत है, तो थ्रेड का उपयोग करने का एकमात्र तरीका मुझे पता है। – gjvdkamp

+0

हाँ, यह सबसे आसान और सबसे सरल तरीका प्रतीत होता है। धन्यवाद – Novellizator

0

इस फ़ंक्शन को थ्रेड में चलाएं और 3 सेकंड या के बाद इसे मार दें इस फ़ंक्शन के अंदर विलुप्त समय की जांच करें (मुझे लगता है कि यह लूप है)।

+1

यह फ़ंक्शन को चेक लूप में बदल देगा, जिससे इसे कोई अन्य कार्यक्षमता नहीं मिल जाएगी। धागे को मारना भी गारंटी नहीं है। जब तक यह समारोह से बाहर निकलता है तब तक यह तब तक नहीं मारा जाएगा। –

0

चूंकि सी # और .नेट फ्रेमवर्क रीयल-टाइम वातावरण नहीं हैं, इसलिए आप 3 सेकंड की गणना भी गारंटी नहीं दे सकते हैं। यहां तक ​​कि यदि आप इसके करीब आना चाहते थे, तो भी आपको विधि में हर दूसरे कॉल से पहले

if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier; पर कॉल करना होगा।

यह सब गलत है इसलिए नहीं, मुझे जो कुछ पता है उससे करने का कोई विश्वसनीय तरीका नहीं है।

आप इस समाधान

https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time

कोशिश कर सकते हैं लेकिन मैं सिर्फ .net आवेदन में ऐसी बातें नहीं करते हालांकि।

+0

हाय, अधिकतम। माइक्रोसॉफ्ट विंडोज़ भी रीयल-टाइम ओएस –

+0

नहीं है, आप Win32 और इंटरऑप का उपयोग कर विंडोज़ पर हाय परफॉमेंस काउंटर के साथ कॉलबैक का उपयोग कर सकते हैं, फिर –

+0

@Artur, कारण मैंने .NET और विंडोज़ के बारे में नहीं कहा है, क्योंकि सी # को भी निष्पादित किया जा सकता है मोनो के माध्यम से यूनिक्स-आधारित ओएस, और मुझे यकीन नहीं है कि उन सभी मोनो-सहायक ओएस वास्तविक समय नहीं हैं। रीयल-टाइम सिस्टम को इकट्ठा करना संभव हो सकता है, लेकिन मोनो सबसे अधिक संभावना वास्तविक समय कभी नहीं होगा, साथ ही नेट, बस क्योंकि इसकी आवश्यकता नहीं है, वर्तमान में। –

0

अगर मौजूद है

+0

क्या एक प्रबंधित थ्रेड को मारने का एपीआई तरीका तत्काल सुनिश्चित करता है (अगले प्रोसेसर पुनरावृत्ति पर) थ्रेड मारता है? –

3

आप टास्क समानांतर लाइब्रेरी इस Task.WaitAll()

using System.Threading.Tasks; 

void CutoffAfterThreeSeconds() { 

    // start function on seperate thread 
    CancellationTokenSource cts = new CancellationTokenSource(); 
    Task loop = Task.Factory.StartNew(() => Loop(cts.Token)); 

    // wait for max 3 seconds 
    if(Task.WaitAll(new Task[]{loop}, 3000)){ 
     // Loop finished withion 3 seconds 
    } else { 
     // it did not finish within 3 seconds 
     cts.Cancel();   
    }   
} 

// this one takes forever 
void Loop() { 
    while (!ct.IsCancellationRequested) { 
     // your loop goes here 
    } 
    Console.WriteLine("Got Cancelled"); 
} 

इस के साथ लागू किया गया है एक अलग धागे पर अन्य कार्य शुरू कर देंगे में कांटा का उपयोग कर सकते/पैटर्न में शामिल होने, और फिर इसके लिए 3000 मिलीसेकेंड के लिए प्रतीक्षा समाप्त। यदि यह टाइमआउट के भीतर खत्म हो गया है, तो यह सच हो जाता है, अन्यथा झूठी है ताकि आप यह तय कर सकें कि आगे क्या करना है।

आप अन्य धागे से संवाद करने के लिए CancellationToken का उपयोग कर सकते हैं कि इसका परिणाम अब आवश्यक नहीं है, इसलिए यह शानदार रूप से बंद हो सकता है।

सम्मान गर्ट-जनवरी

+0

ठीक है, यह आसान और प्रयोग योग्य लगता है :) एक आखिरी सवाल: मैं किसी भी तरह से चल रहे लूप() को कैसे रद्द कर सकता हूं? – Novellizator

+0

इस बात पर निर्भर करता है कि आप वहां क्या कर रहे हैं ... क्या यह किसी प्रकार का लूप है (जिसमें आप रद्दीकरण टोकन को छीन सकते हैं?) या आप किसी अन्य कोड में कॉल करते हैं जिसे आप नहीं बदल सकते हैं? यह रणनीति निर्धारित करता है। यदि लंबी रन्निग ऑपरेशन आपका कोड है, तो आप रद्दीकरण टोकन को देख सकते हैं।यदि यह कुछ अन्य कोड है तो आपको कम दोस्ताना और वास्तव में धागे को मारने की आवश्यकता हो सकती है। हालांकि यह असंगत स्थिति का कारण बन सकता है। मैं रद्दीकरण टोकन के साथ उदाहरण अपडेट करूंगा। – gjvdkamp

+0

ठीक अद्यतन उदाहरण – gjvdkamp

44

अच्छी तरह से ..., मैं एक ही सवाल था, और यहां सभी जवाब पढ़ने और संदर्भित किया जाता ब्लॉगों के बाद, मैं इस के लिए बस गए,

यह मुझे एक समय सीमा के साथ कोड का किसी भी ब्लॉक निष्पादित, आवरण प्रणाली की घोषणा की सुविधा देता है

public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock) 
    { 
     try 
     { 
      Task task = Task.Factory.StartNew(() => codeBlock()); 
      task.Wait(timeSpan); 
      return task.IsCompleted; 
     } 
     catch (AggregateException ae) 
     { 
      throw ae.InnerExceptions[0]; 
     } 
    } 

और का उपयोग करें कि सी # में इस

// code here 

    bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000),() => 
    { 
     // 
     // Write your time bounded code here 
     // 
    }); 

    //More code 
+4

मेरी समझ से, यह कार्रवाई कोड को रोक नहीं देगा अगर यह अभी भी समय के बाद चल रहा है। आपके बेंचमार्किंग परिदृश्य में यदि आपके समांतर में एकाधिक कोड चल रहे हैं तो आपके परिणामों को बहुत बदलना चाहिए। –

+0

मुझे लगता है कि आपको 'कार्य कार्य = नया कार्य (कोडब्लॉक) लिखना होगा; task.Wait (समयावधि); task.Start(); वापसी कार्य। पूरा हो गया; 'क्योंकि आपके कोड के साथ, आप विधि शुरू कर रहे हैं और इसे x बार प्रतीक्षा करने के लिए कहें। लेकिन असल में केवल एक कार्य प्रतीक्षा करें और कार्य शुरू करें एक बेहतर दृष्टिकोण है। –

2

सबसे अच्छा तरीका है बीच में समारोह को रोकने के लिए की तरह कोड के किसी भी ब्लॉक रैप करने के लिए समारोह में return कीवर्ड है, लेकिन कैसे मैं जानता हूँ कि जबउपयोग करने के लिए करते हैंकीवर्ड को फ़ंक्शन को मध्य में रोकने के लिए, कम से कम 3 सेकंड तक रहता है? StopwatchSystem.Diagnostics से कक्षा का उत्तर है। यह जटिल फ़ंक्शन जो 2 सेकंड से 5 मिनट के बीच रहता है (इनपुट डेटा के आधार पर) तार्किक रूप से कई लूप का उपयोग करता है, और यहां तक ​​कि रिकर्सन भी हो सकता है, इसलिए आपके लिए मेरा समाधान यह है कि, उस फ़ंक्शन के पहले पंक्ति कोड पर, Stopwatch का उदाहरण बनाएं new कीवर्ड के साथ System.Diagnostics का उपयोग कर, यह स्टॉपवॉच वर्ग के Start() कार्यप्रणाली को कॉल करके प्रारंभ करें, और प्रत्येक पाश और पाश के लिए में, शुरुआत में, निम्न कोड जोड़ें:

if (stopwatch.ElapsedMilliseconds >= 3000) { 
    stopwatch.Stop(); 
    // or 
    stopwatch.Reset(); 
    return; 
} 

(टिप: आप इसे टाइप कर सकते हैं एक बार हाथों से, इसे Ctrl + C कॉपी करें, और उसके बाद इसे Ctrl + V चिपकाएं)। यदि वह फ़ंक्शन स्मृति को सहेजने के लिए रिकर्सन का उपयोग करता है, तो पहले इसे स्थानीय उदाहरण के रूप में बनाने के बजाय स्टॉपवॉच वैश्विक उदाहरण बनाएं, और इसे शुरू करें यदि यह कोड की शुरुआत में नहीं चल रहा है। आप स्टॉपवॉच क्लास के IsRunning के साथ जान सकते हैं। उसके बाद पूछें कि क्या विलुप्त समय 3 सेकंड से अधिक है, और यदि हां (true) स्टॉपवॉच को रोकें या रीसेट करें, और रिकर्सन लूप को रोकने के लिए return कीवर्ड का उपयोग करें, फ़ंक्शन में बहुत अच्छी शुरुआत करें, यदि आपका फ़ंक्शन मुख्य रूप से रिकर्सन के कारण लंबे समय तक रहता है loops से अधिक। यही है वो। जैसा कि आप देख सकते हैं, यह बहुत आसान है, और मैंने इस समाधान का परीक्षण किया, और परिणामों से पता चला कि यह काम करता है! यह अपने आप का प्रयास करें!

+0

सबसे अच्छा जवाब बिंदु के लिए सरल और त्वरित है। आपके पास अच्छी सामग्री है लेकिन आपको संशोधन पर विचार करना चाहिए। – WolfLink