2010-12-19 14 views
44

मैं ऑनलाइन देखें कि यह दर्शाता है कि मैं myThread.Join(); का उपयोग जब मैं जब तक एक और धागा खत्म मेरी धागा ब्लॉक करना चाहते हैं। (उन चीजों में से एक जो मुझे इस बारे में नहीं मिलता है वह है यदि मेरे पास एकाधिक धागे हैं)।मल्टीथ्रेडिंग: मैं एक जॉइन का उपयोग कब करूंगा?

लेकिन आम तौर पर, मैं तब नहीं मिलता जब मैं .Join() या ऐसी स्थिति का उपयोग करता हूं जो इसके लिए उपयोगी है। क्या कोई मुझे यह समझा सकता है कि मैं चौथा ग्रेडर हूं? समझने के लिए बहुत सरल स्पष्टीकरण मेरे उत्तर वोट मिलेगा।

उत्तर

49

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

List<Thread> workerThreads = new List<Thread>(); 
List<int> results = new List<int>(); 

for (int i = 0; i < 5; i++) { 
    Thread thread = new Thread(() => { 
     Thread.Sleep(new Random().Next(1000, 5000)); 
     lock (results) { 
      results.Add(new Random().Next(1, 10)); 
     } 
    }); 
    workerThreads.Add(thread); 
    thread.Start(); 
} 

// Wait for all the threads to finish so that the results list is populated. 
// If a thread is already finished when Join is called, Join will return immediately. 
foreach (Thread thread in workerThreads) { 
    thread.Join(); 
} 

Debug.WriteLine("Sum of results: " + results.Sum()); 

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

+1

आपको 'int value = i;' जैसे कुछ जोड़ने की आवश्यकता है एक नए थ्रेड में शामिल होने से पहले फूर-लूप में। क्योंकि थ्रेड शुरू होने से पहले 'मैं' बढ़ रहा है और योग गैर-निर्धारक होगा। –

8

जॉइन का उपयोग मुख्य रूप से किया जाता है जब आपको प्रतीक्षा करना होगा कि थ्रेड (या उनमें से एक समूह) आपके कोड के साथ प्रक्रिया करने से पहले समाप्त हो जाएगा।

इस कारण से विशेष रूप से उपयोगी होता है जब आपको थ्रेड निष्पादन से परिणाम एकत्र करने की आवश्यकता होती है।

नीचे अराफांगियन टिप्पणी के अनुसार, थ्रेड बनाने के बाद आपको कुछ सफाई/हाउसकीपिंग कोड करने की आवश्यकता होने पर थ्रेड में शामिल होना भी महत्वपूर्ण है।

+1

उल्लेख करना चाहिए कि निकास के लिए तैयारी की प्रक्रिया को साफ करते समय यह महत्वपूर्ण हो सकता है। – Arafangion

+0

@Arafangion: ठीक है! – Lorenzo

15

निम्नलिखित कोड का टुकड़ा में, मुख्य थ्रेड कॉल Join() जो इसे खत्म करने के लिए सभी पैदा धागे तक प्रतीक्षा करनी पड़ती:

static void Main() 
{ 
    Thread regularThread = new Thread(ThreadMethod); 
    regularThread.Start(); 

    Thread regularThread2 = new Thread(ThreadMethod2); 
    regularThread2.Start(); 

    // Wait for spawned threads to end. 
    regularThread.Join(); 
    Console.WriteLine("regularThread returned."); 

    regularThread2.Join(); 
    Console.WriteLine("regularThread2 returned."); 
} 

ध्यान दें कि अगर आप भी थ्रेड पूल से एक धागा अप काता (QueueUserWorkItem का उपयोग कर उदाहरण के लिए), उस पृष्ठभूमि धागे की प्रतीक्षा न करें। आपको ऑटोरसेट इवेंट का उपयोग करने जैसे कुछ अन्य तंत्र को लागू करने की आवश्यकता होगी।

एक उत्कृष्ट परिचय सूत्रण करने के लिए, मैं पढ़ने की सलाह जो Albahari के नि: शुल्क Threading in C#

+1

मुफ्त और मूल्यवान ईबुक के लिंक के लिए धन्यवाद –

7

यह थ्रेड Join के उपयोग को प्रदर्शित करने के लिए बहुत ही सरल प्रोग्राम है। कृपया बेहतर समझने के लिए मेरी टिप्पणियों का पालन करें। इस कार्यक्रम को इस तरह लिखें।

using System; 
    using System.Threading; 


    namespace ThreadSample 
    { 
     class Program 
     { 
      static Thread thread1, thread2; 
      static int sum=0; 
      static void Main(string[] args) 
      { 
       start(); 
       Console.ReadKey(); 
      } 
      private static void Sample() { sum = sum + 1; } 
      private static void Sample2() { sum = sum + 10; } 

      private static void start() 
      {  
       thread1 = new Thread(new ThreadStart(Sample)); 
       thread2 = new Thread(new ThreadStart(Sample2)); 
       thread1.Start(); 
       thread2.Start(); 
      // thread1.Join(); 
      // thread2.Join(); 
       Console.WriteLine(sum); 
       Console.WriteLine(); 
      } 
     } 
} 

1.First समय रन के रूप में यह (टिप्पणी के साथ) है: तो 0 (प्रारंभिक मूल्य) हो जाएगा परिणाम या 1 (जब धागा 1 समाप्त हो गया) या 10 (या धागा समाप्त हो गया)

2.Run टिप्पणी thread1.Join() को दूर करने के साथ: परिणाम होना चाहिए हमेशा से ज्यादा 1 .because thread1.Join() निकाल दिया और धागा 1 से पहले योग प्राप्त समाप्त किया जाना चाहिए।

साथ

3.Run सभी coments को हटाने: परिणाम हमेशा 11

0

एक devopsEMK की पोस्ट से विधि "नमूना" में 300 मि.से की देरी और "Sample2" में 400 मि.से की देरी जोड़ने होगा होना चाहिए समझने में आसान है।

ऐसा करके आप देख सकते हैं कि "thread1.Join();" से टिप्पणी को हटाकर रेखा, मुख्य धागा "थ्रेड 1" के लिए इंतजार कर रहा है और केवल आगे बढ़ने के बाद।

0

एक अन्य उदाहरण है, जब आपके कार्यकर्ता धागा मान लें कि एक इनपुट स्ट्रीम जबकि पढ़ने विधि हमेशा के लिए चला सकते हैं से पढ़ता है और आप किसी भी तरह इस से बचना चाहते हैं - एक और प्रहरी धागा का उपयोग कर समय समाप्त लगाने से:

// worker thread 
var worker = new Thread(() => { 
    Trace.WriteLine("Reading from stream"); 

    // here is the critical area of thread, where the real stuff happens 
    // Sleep is just an example, simulating any real operation 
    Thread.Sleep(10000); 

    Trace.WriteLine("Reading finished"); 
}) { Name = "Worker" }; 
Trace.WriteLine("Starting worker thread..."); 
worker.Start(); 

// watchdog thread 
ThreadPool.QueueUserWorkItem((o) => { 
    var timeOut = 5000; 
    if (!worker.Join(timeOut)) 
    { 
     Trace.WriteLine("Killing worker thread after " + timeOut + " milliseconds!"); 
     worker.Abort(); 
    } 
}); 
संबंधित मुद्दे