2015-12-19 13 views
9

मैं मल्टीथ्रेडिंग को समझने की कोशिश कर रहा हूं। मेरे पास एक उदाहरण है जो कंसोल ऐप में मुख्य विधि से दो धागे चलाता है।मल्टीथ्रेडिंग को समझना सी #

new Thread(() => 
{ 
    for (int x = 0; x < 10; x++) 
    { 
     Console.WriteLine("First :" + x); 
    } 
}).Start(); 

new Thread(() => 
{ 
    for (int x = 0; x < 10; x++) 
    { 
     Console.WriteLine("Second :" + x); 
    } 
}).Start(); 

Console.ReadKey(); 

क्या हो रहा है, है मेरे कंसोल काला, उस पर लिखा कुछ भी नहीं आ रहा है, लेकिन यह उचित परिणाम प्रदर्शित करता है जब मैं किसी भी कुंजी तो दबाएँ। क्यूं कर?

+0

अंतिम पढ़ने के लिए अंतिम ReadKey – Steve

+3

हटाएं क्योंकि 'IO' ऑपरेशन 'कंसोल' को सिंक्रनाइज़ किया गया है। 'ReadKey()' 'IO 'पर एक ब्लॉक रखता है। – Rob

+0

ReadKey() एक कीस्ट्रोक – Idos

उत्तर

3

हमें (प्रश्न के अंतर्गत टिप्पणियों को देखकर) नई धागे Console.ReadKey() से पहले पूरी तरह से अमल कहा जाता है, को देखने से कुछ हैं, जबकि अन्य प्रारंभिक धागा नया क्रियान्वित नए लोगों को जगह ले लेना, इनपुट के लिए इंतज़ार कर Console.ReadKey()के माध्यम से से पहले देखना धागे।

आप सब अपने स्वयं बात कर तीन सूत्र, सभी संभावित कंसोल के लिए लिख और अन्य तर्क प्रदर्शन मिल गया है, और आप नियंत्रण एक किसी विशेष समय पर निष्पादित करता है जिनमें से में वास्तव में नहीं कर रहे हैं।

Eric से, यह व्यवहार अपेक्षित है, और जिस तरह से आप नए धागे को निष्पादित कर रहे हैं, वह अनुमानित रूप से अप्रत्याशित है। (फिर से पोस्ट किया उसकी टिप्पणी यहाँ मामले में टिप्पणी साफ हो जाने)

फिर से मेरे दो मौलिक नियम पढ़ें: (1) प्रोग्राम हैं जो दो धागे पर यूआई टूट रहे हैं करने की कोशिश, और (2) नहीं है सामान्य रूप से व्यवहार करने की अपेक्षा करें। मुझे कोई उम्मीद नहीं है कि टूटा हुआ कार्यक्रम किसी भी व्यवहार का उत्पादन करेगा। इसके अलावा, मुझे उम्मीद नहीं है कि एक टूटे हुए कार्यक्रम का व्यवहार कई रनों या मशीनों के पार संगत होगा। मैं यह भी उम्मीद नहीं करता कि व्यवहार असंगत होगा। टूटे हुए प्रोग्राम टूटा हुआ है; उन्हें अपने बुरे व्यवहार में लगातार या असंगत होने की आवश्यकता नहीं है।

एक कॉल जब तक नई धागे निष्पादन पूरा कर रहे हैं, आप प्रारंभिक (मुख्य) धागा (जो बुला धागा होता है) को ब्लॉक करने की अनुमति देगा है, और है कि Thread.Join है। आप अभी भी नियंत्रण में नहीं हैं कि दो नए थ्रेड निष्पादित करते हैं और कंसोल पर लिखते हैं, लेकिन कम से कम प्रारंभिक धागा रुक गया है।

var threads = new Thread[] { 
    new Thread(() => 
    { 
     for (int x = 0; x < 10000; x++) 
     { 
      Console.WriteLine("First :" + x); 
     } 
    }), 
    new Thread(() => 
    { 
     for (int x = 0; x < 10000; x++) 
     { 
      Console.WriteLine("Second :" + x); 
     } 
    }) 
}; 

// start the threads 
foreach (var t in threads) 
    t.Start(); 

// block the initial thread until the new threads are finished 
foreach (var t in threads) 
    t.Join(); 

// Now the following line won't execute until both threads are done 
Console.ReadKey(); 
+0

यह उत्तर एक महत्वपूर्ण बिंदु को दर्शाता है: जब आप बहुप्रचारित दुनिया में रहते हैं जहां सब कुछ चल रहा है, उसे अभी भी रहने के लिए मजबूर नहीं किया जाता है, तो आदेश में क्या होता है इसके बारे में केवल थोड़ी सी गारंटी होती है।जैसे ही होता है, थ्रेड शुरू करना और जुड़ना * करना * आपको कुछ गारंटी देता है: शुरू होने से पहले जो तर्कसंगत रूप से होता है वह वास्तव में शुरू होने से पहले होता है, और जब तक धागे के काम को पूरा नहीं किया जाता है तब तक शामिल नहीं होंगे। अब: मैंने जो अभी कहा वह असली स्थिति का एक ओवरम्प्लिफिकेशन है। सी # विनिर्देश विवरण देता है। –

+0

धन्यवाद @Eric, आपकी अंतर्दृष्टि की सराहना की। उम्मीद है कि यह उत्तर किसी की मदद करता है, भले ही यह पूरी तस्वीर न हो। और अगर किसी को भी एक अच्छा डुप्लिकेट मिलता है जो पहले से ही इसका उत्तर देता है (मैं शर्त लगाऊंगा), मैं खुशी से इस जवाब को हटा दूंगा और बेहतर तरीके से स्थगित कर दूंगा। –

+0

+1 शामिल होने के लिए, लेकिन मुझे लगता है कि अगर कोई थ्रेड कुछ संसाधनों की प्रतीक्षा कर रहा है (जैसे कंसोल। रीडकी कीबोर्ड इनपुट के लिए इंतजार कर रहा है।) और यह नहीं मिल रहा है तो अन्य थ्रेड प्रसंस्करण शुरू हो जाएंगे। यहां मैं डीबगर का उपयोग करके निष्पादन को रोककर अधिक समय तक इंतजार कर रहा हूं लेकिन फिर भी अन्य धागे (यानी मुख्य धागे के अलावा निष्पादित नहीं होते हैं)। इसका मतलब है कि मुझे वह असीमित व्यवहार नहीं मिल रहा है जिसे मैं प्राप्त करना चाहता था। मेरा मुद्दा यह है कि यदि मेरा एप्लिकेशन कुंजीपटल इनपुट की प्रतीक्षा कर रहा है तो अन्य थ्रेडों को अपना निष्पादन शुरू करना चाहिए था। – Imad

0

मुझे पहले स्पॉन्टेड थ्रेड को थ्रेड 1 के रूप में कॉल करने दें, अगले स्पॉन्डेड थ्रेड को थ्रेड 2 के रूप में कॉल करें। इसके अलावा चलिए थ्रेड को कॉल करते हैं जो थ्रेड 1 और थ्रेड 2 को मेनथ्रेड के रूप में बनाता है।

शिथिल बोल, वहाँ कोई गारंटी नहीं है कि thread1 में कोड thread2 या mainthread की कि इससे पहले निष्पादित हो जाएगा। तो विभिन्न परिस्थितियों के आधार पर, Console.ReadKey() को रोकने से पहले यह Console.WriteLine() निष्पादित कर सकता है।
यह Console.ReadKey() के लिए क्यों रुकता है आप पूछ सकते हैं; चूंकि कंसोल I/O सिंक्रनाइज़ किया गया है। कंसोल के चारों ओर एक lock बयान। * कॉल यह और भी स्पष्ट

आप अन्य 2 धागे बुला Console.ReadKey() (अवरुद्ध I/O कॉल) से पहले प्रसंस्करण समाप्त करना चाहते हैं, तो आप कॉल करना चाहिए (डेमो कोड के लिए) कर सकता है thread1.Join() और thread2.Join()Console.ReadKey()

+0

कंसोल I/O सिंक्रनाइज़ किया गया है। यह समझ आता है। – Imad

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