2011-12-20 18 views
12

ben varsa bu: Farklı bir ile DoSomethingÇoklu ve .NET kapanışları

public string DoSomething(string arg) 
{ 
    string someVar = arg; 
    DoStuffThatMightTakeAWhile(); 
    return SomeControl.Invoke(new Func<string>(() => someVar)); 
} 

Ve bu yöntem birden çok iş parçacığı aynı anda çağrılabilir ve bir iplik DoStuffThatMightTakeAWhile sıkışmış edilir ve daha sonra ikinci bir iş parçacığı çağırır arg, bu, tüm iş parçacıkları için someVar değerini değiştirecek ve sonuç olarak, her iki çağrı için1 ikinci sürümü döndürür veya her bir iş parçacığı için bir someVar var mı?

EditAction benim Func olması gerektiğini düşünüyorum.

cevap

16

karmaşa sonucu vardır. Bu cevaplar, çoğunlukla yerel değişkenlerin "iş parçacığı yığınında" ayrıldığı gerçeğine dayanır. yanlış ve alakasız. Yerel değişken, geçici bir havuzda veya uzun süreli depolama havuzunda ayrılabileceğinden, bu yanlıştır; geçici bir havuzda tahsis edilmiş olsa bile, bunun yığın bellek olması gerekmez; bir kayıt olabilir. Bu konuyla alakası yok, çünkü depolama havuzunun hangi havuza verildiği kimin umurunda? İlgili gerçek, yöntem aktivasyonu başına üst düzey bir yerel değişkenin tahsis edilmesidir. Daha genel olarak, bir bloktaki yerel bir değişken girilen blok başına bir kez tahsis edilir; Bir ilmiğin gövdesinde bildirilen yerel bir değişken, örneğin, döngü her gittiğinde tahsis edilir.

Yani, sorunuzu ele alalım:

Bu yöntem birden çok iş parçacığı aynı anda çağrılabilir.bir iplik DoStuffThatMightTakeAWhile sıkışmış ve daha sonra ikinci bir iş parçacığı DoSomething farklı arg ile çağrıları ise, bu tüm iş parçacıkları için someVar değerini değiştirecek?

sayılı DoSomething arasında her aktivasyon için yeni bir "SomeVar" vardır.

birer iş parçacığı için var SomeVar olacak?

biri "SomeVar" Her aktivasyonu için var olacaktır. Bir iş parçacığı tam olarak bir aktivasyon yaparsa, iş parçacığı başına tam olarak bir tane VAR olacaktır; Eğer bir iplik bir milyon aktivasyon yaparsa, o zaman bir milyon olur. Hem okur ve bir yerel değişken yazan bir temsilci yaparsanız ve birden fazla iş parçacığı, o zaman tüm aktivasyonları temsilci payının dışarı bu temsilciyi el: bahsedilen

Jon Hanna cevabı da doğru aynı yerel değişken. Sizin için oluşturulan sihirli iplik güvenliği yoktur; Bunu yapmak istiyorsanız iplik güvenliğini sağlamaktan sorumlusunuz.

+0

Yani birkaç kelimeyle, 'dize myVar gibi bir beyanı;' Ben 'new' anahtar kelime ile bir nesne oluşturarak ediyorum gibi yeni bir' hemen hemen myVar' __create__ olacak? Bu aynı zamanda özyinelemeli çağrılar için de geçerli olur mu (eğer 'DoSomething' 'DoSomething' olarak adlandırılırsa)? – Juan

+2

@jsoldi: yönlü bellek ayırıcısı yeni yerli oluşturur ve nesneler perde arkasında çok farklı olabilir için yolu yeni depolama oluşturur, ancak kavramsal olarak ikisi de aynı şeydir. Ve evet, özyinelemeli çağrılar * aktivasyonlar * sadece özyinelemeyen aramalar gibi. Her * aktivasyon * yeni bir grup yerli halkı alır. –

+1

Neden buna "yöntem çağrısı" diyorsunuz ve "yöntem çağrısı" değil. Bu özel bir dönem mi? – Restuta

7

Geçerli iş parçacığı yığınında depolanan yerel değişkenler, böylece her iş parçacığının kendi yığını ve her biri kendi someVar değişkenine sahip olacaktır. her iş parçacığı farklı değerler olacaktır yana

new Action(() => someVar)); 

o someVar kendi değerdir yakalayacaktır. Eric belirttiği gibi

Düzenleme I söyleyerek basitçe yanlış oldu. Doğru açıklama için cevabına bakın.

+1

söyleyen "Yerel değişkenler geçerli iş parçacığı yığınının saklanan" doğru değil. Bir kapanışta yakalanan herhangi bir değişken yığın üzerinde tahsis edilir. –

+0

Jason haklı. Bu cevapta ses mantığı yok. –

+0

Evet, benim kötüyüm, cevabımı değiştirmeyeceğim, çünkü birincisi sadece mükemmel. – Restuta

1

Belirtildiği gibi, DoSomething isabet eden her bir iş parçacığı yığınında ayrı bir someVar oluşturuyor ve bu nedenle hiçbir iş parçacığının someVar üzerinde başka bir etkisi yoktur.

O olsa kayda değer olduğunu yerel bir kapatma yakalanır ve bu kapsamda başlatılan çoklu iş parçacığı bunun gerçekten bile söz konusu olduğunda, birbirini görür değerleri etkileme farklı konuları neden olabilir, varsa normalde başka bir yöntem etkileyebileceği için değil bir şey düşünürdüm değer türleri (- kapanışları sınıf yöntemleri gibi değildir, bu şekilde:

public static void Main(string[] args) 
{ 
    int x = 0; 
    new Thread(() => {while(x != 100){Console.WriteLine(x);}}).Start(); 
    for(int i = 0; i != 100; ++i) 
    { 
     x = i; 
     Thread.Sleep(10); 
    } 
    x = 100; 
    Console.ReadLine(); 
} 

gösterir bu

+0

Eğer doğru anlıyorsam, örneğinizde her iş parçacığı tarafından erişilen yalnızca bir "x" (ana iş parçacığında oluşturulan) var mı? – Juan

+0

Tam olarak, el ile oluşturulan iş parçacığı onu artırır, ana iş parçacığı artırır. –

+1

BazıVar'ın yığında ilk sırada yer almadığını unutmayın. Kapalı mekanda yaşayanlar, yaşam süreleri uzatıldığı için yığına tahsis edilir. –