2014-07-06 9 views
29
Task.Factory.StartNew(() => 
    { 
    new Class1(); 
    }) 

Task.Factory.StartNew(() => 
    { 
    new Class2(); 
    }) 

Class1 और class2 के निर्माता में मेरे पास है:एक दूसरे के बाद दो कार्य एक ही यादृच्छिक मूल्य उत्पन्न करते हैं?

var timeout = new Random().Next(0, 5000); 
Debug.Print(timeout.ToString()); 

यादृच्छिक मान 'टाइमआउट' हमेशा दोनों वर्गों में एक ही है। मुझे समझ में नहीं आता क्यों ..

यदि मैं कार्यों के निर्माण के बीच एक विराम जोड़ता हूं तो यह वही नहीं है।

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

मुझे समझ नहीं आता कि यह कैसे संबंधित है के लिए "Random String Generator Returning Same String"।

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

+9

** मॉडरेटर नोट **: यदि आप इस प्रश्न पर चर्चा करना चाहते हैं, तो हमारे पास एक चमकदार मेटा पोस्ट है जहां आप ऐसा कर सकते हैं] (http://meta.stackoverflow.com/questions/262791)। कृपया इस प्रश्न पर टिप्पणी * विषय पर रखें: ओपी से स्पष्टीकरण मांगना; इस प्रश्न के दायरे को अपने प्रतिस्पर्धी डुप्लिकेट के साथ-साथ निर्धारित करना। जो कोई सी # में काम करता है, मैं कह सकता हूं कि यह तुरंत स्पष्ट नहीं होगा कि दोनों मुद्दों के समान मूल कारण हैं; और यह एक ऐसा प्रश्न है जो 'कार्यों का उपयोग करके इसे कैसे लिखूं' के उत्तर से भी लाभान्वित होगा। –

उत्तर

41

मुझे समझ में नहीं आता कि यह "रैंडम स्ट्रिंग जनरेटर रिटर्निंग समान स्ट्रिंग" से कैसे संबंधित है।

यह सीधे संबंधित नहीं है, हालांकि मूल कारण समान है।

डिफ़ॉल्ट बीज मूल्य सिस्टम घड़ी से ली गई और परिमित संकल्प है: - शिष्टाचार documentation को Why do I keep getting two of same random values in this code?

यह new Random क्या करता है की an explanation शामिल हैं: एक बेहतर डुप्लिकेट इस सवाल का होगा। नतीजतन, अलग-अलग रैंडम ऑब्जेक्ट्स जिन्हें डिफॉल्ट कन्स्ट्रक्टर को कॉल द्वारा निकट उत्तराधिकार में बनाया गया है, में समान डिफ़ॉल्ट बीज मान होंगे और इसलिए, यादृच्छिक संख्याओं के समान सेट तैयार करेंगे।

दूसरे शब्दों में: यदि आप त्वरित उत्तराधिकार में Random ऑब्जेक्ट्स बनाते हैं, तो वे वही यादृच्छिक संख्या अनुक्रम उत्पन्न करेंगे।

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

यह अप्रासंगिक है कि क्या इन वस्तुओं अलग धागे (या Task रों) में बनाए जाते हैं - वे केवल सिस्टम समय जब वे बनाई गई हैं पर निर्भर करते हैं, और कुछ नहीं पर। वे वास्तव में एक दूसरे से स्वतंत्र हैं, जैसा कि आपने कहा था। लेकिन वे दोनों एक ही बीज मूल्य पर निर्भर करते हैं, जो सृजन में सिस्टम समय है।


इस को सुलझाने का सही तरीका Random वर्ग के केवल एक उदाहरण है करने के लिए आमतौर पर है।- वास्तव में, इस तरह के कोड: new Random().Next(…) कोड गंध है, क्योंकि यह Random वर्ग का गलत उपयोग करता है: आपको प्रत्येक कॉल के लिए एक नया उदाहरण उत्पन्न नहीं करना चाहिए; इसके बजाय, आपको यादृच्छिक संख्याओं के अनुक्रम उत्पन्न करने के लिए एक ही उदाहरण का पुन: उपयोग करना चाहिए।

दुर्भाग्यवश, आप Random उदाहरण को विभिन्न समवर्ती कार्यों में उपयोग नहीं कर सकते हैं, क्योंकि relevant method थ्रेड सुरक्षित नहीं है - यानी, इसे कई धागे से कॉल करने के साथ-साथ दौड़ की स्थिति भी हो सकती है। इस के आसपास हो रही के कई तरीके हैं, लेकिन सबसे पक्का तरीका एक स्पष्ट लॉक का उपयोग करने के लिए है:

public Class(Random rng) { 
    lock (rng) { 
     var timeout = rng.Next(5000); 
     Debug.Print(timeout.ToString()); 
    } 
} 

यह ध्यान रखें कि rng को हर पहुँच बंद किया जाना चाहिए महत्वपूर्ण है, अन्यथा इस विवादास्पद है।

var rng = new Random(); 

var tasks = new [] { 
    Task.Run(() => { new Class(rng); }), 
    Task.Run(() => { new Class(rng); }) 
}; 
Task.WaitAll(tasks); 

ध्यान दें कि जब lock(…) ब्लॉक बाहर छोड़ रहा है, यह लग सकता है जैसे कि आप सही परिणाम दे रहे हैं:

अब आप अपने कार्यों को उचित अनियमितता बना सकते हैं और उन्हें चलाने के लिए, और मिलता है। यह समवर्तीता और यादृच्छिकता के साथ काम करने का खतरा है: यह सत्यापित करना मुश्किल है कि आपका परिणाम वास्तव में सही है या फिर यह रास्ते में दूषित हो गया है या नहीं। तो सावधानी के साथ चलना।

+2

स्पष्टीकरण के लिए धन्यवाद! उचित लगता है। – Dimo

10

पैरामीटर रहित Random कक्षा कन्स्ट्रक्टर यादृच्छिक संख्या पीढ़ी एल्गोरिदम के लिए प्रारंभिक बीज निर्धारित करने के लिए समय से संबंधित तरीके का उपयोग करता है।

public Random() 
    : this(Environment.TickCount) { 
} 

यही कारण है कि जब आप एक ही समय में उदाहरण बनाते हैं तो वे एक ही परिणाम उत्पन्न करेंगे।

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