2015-09-16 8 views
5

अद्यतन करने वाले मल्टीथ्रेडिंग समस्या को समझने में कठिनाई है कि क्यों थ्रेड पूरा होने से पहले बहुप्रतिष्ठण मानों को अद्यतन करने में विफल रहता है। क्या अलग धागे में संदर्भ या मूल्यों की अपनी प्रति है?
मान

यदि नहीं, तो मेरी समझ करने के लिए नीचे दिए गए कोड को ठीक से काम करना चाहिए जब MyMethod कहा जाता है, लेकिन अक्सर यह thread.IsAlive से पहले सरणी में कुछ MyType वस्तुओं के उदाहरण का निर्माण नहीं करता झूठा हो जाता है:

class MyClass 
{ 
    static MyType[] obj = new MyType[Environment.ProcessorCount - 1]; 
    void MyMethod() 
    { 
     Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

     for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
     { 
      threads[i] = new Thread(() => FillObjects(i)); 
      threads[i].Priority = ThreadPriority.AboveNormal; 
      threads[i].Start(); 
     } 

     while (threads[i].Any(c => c.IsAlive)) 
     { 
      Thread.Sleep(50); 
     } 
    } 
    void FillObjects(int i) 
    { 
     obj[i] = new MyType(); 
     //perform actions with obj[i] to fill it with necessary values 
    } 
} 

उत्तर

6

आपको लूप वैरिएबल के मान को स्थानीय चर में असाइन करने की आवश्यकता है। अन्यथा यह संभव है कि FillObjects(i) का पहला निष्पादन i के बाद निष्पादित किया गया था इसलिए FillObjects(0) कभी नहीं कहा जाता है और इसलिए obj[0] कभी असाइन नहीं किया जाता है।

void MyMethod() 
{ 
    Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

    for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
    { 
     int local = i; 
     threads[i] = new Thread(() => FillObjects(local)); 
     threads[i].Priority = ThreadPriority.AboveNormal; 
     threads[i].Start(); 
    } 

    while (threads.Any(c => c.IsAlive)) 
    { 
     Thread.Sleep(50); 
    } 
} 
+2

अच्छा बिंदु। यदि 'FillObjects()' में पहला कथन 'थ्रेड। स्लीप (1000)' संभवतः केवल 'obj [Environment.ProcessorCount - 1] 'गैर-शून्य होगा क्योंकि लूप ने इसके अंत मूल्य में' i' बढ़ाया होगा पहली वस्तु बनने से पहले। इसके बारे में सोचते हुए, FillObjects() फेंक सकता है क्योंकि लूप से बाहर निकलने से पहले 'i' वास्तव में' पर्यावरण 'प्रोसेसर काउंटर -1' में वृद्धि हुई है और इस प्रकार 'ओबीजे' की सीमा से बाहर है। –

+0

उत्तर के लिए धन्यवाद, वास्तव में यह बड़ी समस्याओं में से एक था, अब यह वस्तुओं को ठीक से चालू करता है। हालांकि धागा बंद होने से पहले सभी परिचालनों को ठीक से पूरा नहीं करता है और यह यादृच्छिक रूप से करता है। कोई सुझाव? – Almis

+0

मुझे अपनी खुद की तार्किक गलती मिली है, अब यह ठीक से काम करता है। – Almis

-1

एक थ्रेड में स्मृति स्थान पर लिखे गए एक बहु प्रोसेसर मशीन (जो आपके पास होना चाहिए) पर कैशिंग के कारण किसी अन्य थ्रेड में दिखाई नहीं दे सकता है। कैश के माध्यम से पढ़ने और लिखने के लिए Thread.VolatileRead और Thread.VolatileWrite पढ़ें।

सीएफ। एक स्पष्टीकरण के लिए the chapter on threading in c# 3.0 in a Nutshell। (प्रश्न के लिए देखो "क्या प्रतीक्षा विधि के लिए" गलत "लिखना संभव है?" यह उदाहरण मूल रूप से आपका मामला है।)

+0

जिज्ञासा से बाहर: क्या मैंने गलत कहा है या लागू नहीं है? –

+0

हालांकि जो डाउनवॉटेड नहीं है: मैं उपरोक्त समस्या को हल करने के लिए अस्थिर रीड/लिखने के लिए परिदृश्य के बारे में नहीं सोच सकता। संक्षेप में सी # से संदर्भित समस्या आईएमएचओ से ऊपर की समस्या से मेल नहीं खाती है और साथ ही मुझे कोई भी कैशिंग समस्या नहीं दिखती है जो अस्थिर हल हो जाएगी। – Linky

+0

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