5

मैं एक पाश में चल रहा हूँ और निम्नलिखित तरीके से कार्य को बंद लात चाहते हैं लगता है:स्टॉपवॉच, सभी कार्य भर में additive हो सिर्फ कार्य अंतराल को मापने के लिए

var iResult = new List<Task>(); 
foreach(var i in myCollection) 
{ 
    var task = Task.Factory.StartNew(() => 
        DoSomething(), TaskCreationOptions.LongRunning); 
    task.ContinueWith(m => myResponseHandler(m.Result)); 
    iResult.Add(task); 
} 

मेरी DoSomething() विधि के भीतर, मैं एक टाइमर है: जब मैं myMsg के ElaspedMilliseconds की मेरी सूची के माध्यम से पुनरावृति

public static myMsg DoSomething() 
{ 
    var timer = System.Diagnostics.Stopwatch.StartNew(); 
    DoLongRunningTask(); //If it matters this hits a REST endpoint (https) 
    timer.Stop(); 

    return new myMsg(timer.ElaspedMilliseconds); 
} 

पूरी तरह से additive हो रहा है - पहले एक पर ElaspedMilliseconds 300 हो सकता है, लेकिन पिछले एक 50000 (50 सेकंड) हो सकता है - जो वास्तव में एक है पंपप्लेमेट टाइम पूरी चीज चलाने के लिए लेता है (जैसा कि एक और टाइमर द्वारा मापा जाता है)।

+1

अपडेट किया गया [मेरा उत्तर] (http://stackoverflow.com/a/16259019/200449)। यह केवल भ्रामक रूप से additive दिखता है क्योंकि ElapsedMilliseconds मान हमेशा बढ़ते क्रम में आउटपुट होते हैं - कार्यों को पूरा करने के क्रम में (कार्य की अवधि के क्रम में) जिसमें वह आदेश नहीं है जिसमें कार्य लॉन्च किए गए थे –

उत्तर

2

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

ओह, मैं भी पहले उलझन में था।

समस्या यह है कि यह केवल अनुकूली (संचय) दिखता है क्योंकि ElapsedTime मान हमेशा बढ़ते क्रम में आउटपुट होते हैं।

तो, अगर मेरे पास है, नीचे मेरी डेमो, शुरूआत के क्रम में के रूप में:

  • 10 सेकंड (10000 msec) के 1 का शुभारंभ किया कार्य की अवधि,
  • 8 सेकंड के 2 कार्य की अवधि (8 000 एमएस),
  • 6 सेकंड (6 000 एमएस) की 3 डी कार्य की अवधि,

तो परिणाम उत्पादन में प्रदर्शित प्रारंभिक आदेश से बाहर - हमेशा increasi के क्रम में कार्यों की एनजी अवधि:

  • उत्पादन में 1: 2 का शुभारंभ किया कार्य की अवधि (8 सेकंड की अवधि)
  • : (6 सेकंड की अवधि का)
  • उत्पादन में 2 3 डी का शुभारंभ किया कार्य की अवधि 3 डी (अंतिम) उत्पादन में:

    from DoSomething 6043 
    from main 6043 
    from DoSomething 8057 
    from main 8057 
    from DoSomething 10058 
    from main 10058 
    
    : 1 का शुभारंभ किया कार्य की अवधि (10 सेकंड की अवधि का)

यहाँ नीचे कंसोल app से उत्पादन होता है 10

और यह स्पष्ट है कि क्यों - क्योंकि तेजी से कार्य हमेशा समाप्त होता है और लंबे समय तक (अधिक समय लेने वाला) कार्य करता है।

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     var iResult = new List<Task>(); 
     for (int i=5; i>2; i--) 
     { 
     int load = i; 
     var task = Task.Factory.StartNew(() => 
         DoSomething(load), TaskCreationOptions.LongRunning); 
     //following commented lines do NOT change the behavior in question 
     task.ContinueWith(m => Console.WriteLine("from main "+m.Result)); 
     //iResult.Add(task); 
     } 
     Console.ReadLine(); 
    } 

    //public static myMsg DoSomething() 
    public static long DoSomething(int load) 
    { 
     Stopwatch timer = System.Diagnostics.Stopwatch.StartNew(); 

     //usage of either prev or following 2 lines produce the same results 
     //Stopwatch timer = new Stopwatch(); //instead of prev .StartNew(); 
     //timer.Start();// instead of prev .StartNew(); 

     Console.WriteLine("***Before calling DoLongRunningTask() " 
       + timer.ElapsedMilliseconds); 
     Console.WriteLine("GetHashCode "+timer.GetHashCode()); 

     DoLongRunningTask(load); 
     timer.Stop(); 

     long elapsed = timer.ElapsedMilliseconds; 
     Console.WriteLine("from DoSomething "+ elapsed); 

     return elapsed;//return new myMsg(timer.ElaspedMilliseconds); 
    } 

    public static void DoLongRunningTask(int load) 
    { 
     Thread.Sleep(2000*load); 
     /******************* another variant of calculation intensive loading 
      load = load; 
      double result = 0; 
      for (int i = 1; i < load*100000; i++) 
        result += Math.Exp(Math.Log(i)); 
     */ 
    } 
    } 
} 
+1

कार्यों के बीच लोड क्यों बदल जाएगा? वे एक ही समय तक चलने वाले हैं। – LightStriker

2

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

आपके पास असीमित थ्रेड पूल नहीं है और कार्य हैंडल जो थ्रेड प्राप्त करते हैं और कब।

LongRunning के बारे में:।।

"यह एक विशिष्ट लंबाई दर असल आप कार्यों का एक बहुत कुछ पैदा कर रहे हैं, LongRunning उनके लिए उपयुक्त नहीं है आप एक या दो कार्यों पैदा कर रहे हैं कि बना रहेगा रहा है आपके आवेदन के जीवनकाल के सापेक्ष कुछ समय के लिए, फिर लॉन्ग राइजिंग कुछ विचार करने के लिए है। आम तौर पर, इसका उपयोग तब तक न करें जब तक कि आपको यह न मिल जाए कि आपको वास्तव में इसकी आवश्यकता है। कवर के तहत, इसके परिणामस्वरूप धागे की एक बड़ी संख्या होगी इस्तेमाल किया जा रहा है, क्योंकि इसका उद्देश्य थ्रेडपूल को काम की वस्तुओं को संसाधित करना जारी रखना है, भले ही एक कार्य एक विस्तृत अवधि के लिए चल रहा हो; यदि वह कार्य पूल से धागे में चल रहा था, तो वह धागा सक्षम नहीं होगा सेवा अन्य कार्यों। आप आमतौर पर केवल LongRun का उपयोग करेंगे अगर आपको प्रदर्शन परीक्षण के माध्यम से पता चला कि इसका उपयोग नहीं किया जा रहा है तो अन्य काम की प्रसंस्करण में लंबी देरी हो रही है। " - स्टीफन Toub

+0

बस इस पर विस्तृत करने के लिए, यदि 'DoLongRUnningTask() 'डेटा के एक साझा टुकड़े पर ताले, यह काफी संभव है कि टाइमर * additive होने में सही है, क्योंकि प्रत्येक व्यक्ति शुरू होता है, तब तक रोकता है जब तक कि पिछले कोई नहीं किया जाता है। इसे एक साधारण देरी कार्य के साथ बदलने की कोशिश करें और देखें कि क्या यह सही समय लगता है। – Bobson

+0

@ बॉब्सन, [मैं इसे पुन: उत्पन्न कर रहा हूं] (http://stackoverflow.com/a/16259019/200449) डेटा –

+0

@LightStriker के किसी भी प्रकार के पाइस पर किसी भी ताले के बिना, तो क्या होगा यदि "DoLongRunningTask()' हो सकता है multithreaded ठीक से ", भले ही यह एक ही समर्पित थ्रेड का पुन: उपयोग कर रहा हो (शायद 'TaskCreationOptions.LongRunning' के कारण सबसे अधिक क्या है)? यहां तक ​​कि जब मैं स्पष्ट रूप से नए उदाहरण 'स्टॉपवॉच टाइमर = नया स्टॉपवॉच();' या इसे उपयोग करने से पहले समय को रीसेट करता हूं, तो 'टाइमर.इप्लेस्ड मिलिसेकंड्स' मान पिछले उदाहरणों में संचय/बढ़ रहा है –

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