2015-09-16 15 views
5

İş parçacığı tamamlanmadan önce çoklu iş parçacığının değerleri güncelleştiremediğini anlamakta güçlük çekiyorum. Ayrı iş parçacığı, referansların veya değerlerin kendi kopyasına sahip midir?
Çoklu iş parçacığı sorunu değeri güncelleştiriliyor

Değilse, benim anlayışıma için aşağıdaki kod MyMethod çağrıldığında düzgün çalışması gerekir, ancak çoğu zaman thread.IsAlive önce dizide bazı MyType nesnelerin örneklerini yaratmaz yanlış olur:

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 
    } 
} 

cevap

6

Döngü değişkeninin değerini bir yerel değişkene atamanız gerekir. Aksi halde, FillObjects(i)'un ilk çalıştırılmasınınnumaralı satırdan sonra çalıştırılmasının mümkün olması dolayısıyla FillObjects(0)'un hiçbir zaman çağrılmaması ve dolayısıyla obj[0]'un hiçbir zaman atanmaması mümkündür.

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

İyi nokta. Eğer FillObjects() 'in ilk ifadesi bir' Thread.Sleep (1000) 'ise, muhtemelen sadece 'obj [Environment.ProcessorCount - 1]' null olur, çünkü bu döngü, son değerine' i 'dönüşürdü ilk nesne oluşturulmadan önce. Bunu düşünürsek, FillObjects() atlayabilir çünkü ben aslında döngüden çıkmadan önce "Environment.ProcessorCount-1" 'e yükseltilir ve böylece' obj 'sınırları dışında kalır. –

+0

Cevabınız için teşekkür ederiz, gerçekten önemli sorunlardan biriydi, şimdi nesneleri doğru bir şekilde örneklendiriyor. Bununla birlikte, iş parçacığı kapanmadan önce tüm işlemleri düzgün şekilde tamamlamaz ve bunu rastgele yapar. Baska öneri? – Almis

+0

Kendi mantıksal hatasını buldum, şimdi düzgün çalışıyor. – Almis

-1

Bir işlemcideki bir bellek konumuna yazılan çok işlemcili bir makinede (sahip olmanız gereken) sonuçlar, önbelleğe alma nedeniyle başka bir iş parçacığında görünmeyebilir. Önbelleği okumak ve yazmak için Thread.VolatileRead ve Thread.VolatileWrite okumalarını kullanın.

Cf. Bir açıklama için the chapter on threading in c# 3.0 in a Nutshell. ("Bekle yönteminin" Yanlış "yazması mümkün mü?". Bu örnek temelde sizin durumunuzdur.)

+0

Merak ediyorum: Söylediklerimin yanlışlığı nedir ya da uygulanamaz mı? –

+0

Düşürülmüş olanı olmasa da: Yukarıdaki sorunu çözmek için volatileRead/Write kullanmak için bir senaryo düşünemiyorum. Kısaca IMHO'daki C# 'dan referans verilen problem, problemin üstündeki eşleşmedir ve uçucu çözücünün çözeceği herhangi bir önbellek problemi göremiyorum. – Linky

+0

@ Linky Hm. Hem statik bir değişkene erişen iki iş parçacığı. Bir iş parçacığı "yazdı" (bu iş parçacığında daha sonra bir olay ile gösterilir). Diğer iş parçacığı, yazı dizisinin perspektifinden yazılan değeri okur ve yazmayı görmez. Buradaki senaryoya çok benziyor. –

İlgili konular