2011-02-23 15 views
8

IEnumerable<string>'u döndüren bir yöntem var, tabii ki yield return <string>; ile işleniyor. Bunun sonucunu işleyen birden fazla iş parçacığına sahip olmak istiyorum, tabii ki tekrar etmeden ve iş parçacığı güvende olmaksızın. Bunu nasıl başarabilirim? - Hemen her konuyu dosyalarının tam sayımını geçiyoruz - unutmayın Her ProcessCopy() çağrı için bir öğe aralığını seçmek zorundaBirden çok iş parçacığı aynı IEnumerable sonucu nasıl işlenir?

C:\Users\esac\Pictures\2000-06\DSC_1834.JPG 
C:\Users\esac\Pictures\2000-06\DSC_1835.JPG 
C:\Users\esac\Pictures\2000-06\.picasa.ini 
C:\Users\esac\Pictures\2000-06\DSC_1834.JPG 
C:\Users\esac\Pictures\2000-06\DSC_1835.JPG 
C:\Users\esac\Pictures\2000-06\.picasa.ini 
C:\Users\esac\Pictures\2000-06\DSC_1834.JPG 
C:\Users\esac\Pictures\2000-06\DSC_1835.JPG 
C:\Users\esac\Pictures\2000-06\.picasa.ini 
C:\Users\esac\Pictures\2000-06\DSC_1834.JPG 
C:\Users\esac\Pictures\2000-06\DSC_1835.JPG 

cevap

9

Bunu, Parallel.ForEach yöntemini kullanarak kolayca yapabilirsiniz.

Write a Simple Parallel.ForEach loop

Her yineleme

görev yöneticisi sıraya alınır. Tüm iterasyonlar gerçekleştirildiğinde döngü kapanacaktır.

var result = GetFiles(source); 

Parallel.ForEach(result, current => { 
    ProcessCopy(current); 
}); 

Console.WriteLine("Done"); 
+0

Güzel, bu benim için çalıştı. Problemin daha iyi çözümü için – esac

+0

+1 ;-) – BrokenGlass

4

:

var result = GetFiles(source); 

for (int i = 0; i < Environment.ProcessorCount; i++) 
{ 
    tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(result); })); 
} 

Task.WaitAll(tasks.ToArray()); 

Ancak bu tekrarlar üreten gibi görünüyor Geçmekte olduğunuz IEnumerable, GetEnumerator() adı verilen bir yönteme sahiptir - sadece bu yöntem çağrıldığında (foreach'ın kapağın altında yaptığı foreach) gerçek Enumerator döndürülür, ardından öğeleri tek tek sıralayabilirsiniz. IEnumerable'u geçtiğiniz için her iş parçacığı GetEnumerator() çağırıyor ve dolayısıyla tüm dosyaları sıralıyor. TPL izin vermedi ve en iyi performans için çalıştırmak için kaç iş parçacığı dışarı iplik havuz figürü - Ben işlemci sayısı hakkında endişe olmaz

foreach(string file in GetFiles(source)) 
{ 
    string fileToProcess = file; 
    tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(fileToProcess); })); 
} 

Task.WaitAll(tasks.ToArray()); 

:

yerine her ProcessCopy() süreç bir dosya için böyle bir şey yapmak .

+0

+1. – Josh

1

Neden istediğinizi yapmak için basit bir LINQ sorgusu kullanmıyorsunuz? TPL zaten sizin için iğrenç Environment.ProcessorCount şeyler her kolları perde arkası

var tasks = 
    from f in GetFiles(source) 
    select Task.Factory.StartNew(() => { ProcessCopy(f); }); 

Task.WaitAll(tasks.ToArray()); 

. Orijinal hatayı çağırmak için

+0

Essentialy, BrokenGlass ile aynı, ancak LINQ ile hoşuma gidiyor. Parallel.ForEach şimdiye kadar temiz görünüyor, ama bu kesinlikle problem hakkında düşünmem gereken yoldur. – esac

İlgili konular