Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, dosya dizinlerinde işlemleri paralelleştirmenin iki yolu gösterilmektedir. İlk sorgu, bir dizindeki GetFiles ve tüm alt dizinlerdeki dosya adları dizisini doldurmak için yöntemini kullanır. Dizinin tamamı doldurulana kadar döndürmediğinden bu yöntem işlemin başlangıcında gecikmeye neden olabilir. Ancak dizi dolduruldıktan sonra PLINQ diziyi paralel olarak hızlı bir şekilde işleyebilir.
İkinci sorgu, sonuçları hemen döndürmeye başlayan statik EnumerateDirectories ve EnumerateFiles yöntemleri kullanır. Büyük dizin ağaçlarını yinelerken bu yaklaşım daha hızlı olabilir, ancak ilk örnekle karşılaştırıldığında işlem süresi birçok faktöre bağlıdır.
Not
Bu örnekler kullanımı göstermek için tasarlanmıştır ve eşdeğer sıralı LINQ to Objects sorgusundan daha hızlı çalışmayabilir. Hızlandırma hakkında daha fazla bilgi için bkz . PLINQ'ta Hızlandırmayı Anlama.
GetFiles örneği
Bu örnekte, ağaçtaki tüm dizinlere erişiminiz olduğunda, dosya boyutları büyük olmadığında ve erişim süreleri önemli olmadığında basit senaryolarda dosya dizinleri üzerinde nasıl yineleme yapılacağını gösterir. Bu yaklaşım, dosya adları dizisi oluşturulurken başlangıçta bir gecikme süresi içerir.
// Use Directory.GetFiles to get the source sequence of file names.
public static void FileIterationOne(string path)
{
var sw = Stopwatch.StartNew();
int count = 0;
string[]? files = null;
try
{
files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("You do not have permission to access one or more folders in this directory tree.");
return;
}
catch (FileNotFoundException)
{
Console.WriteLine($"The specified directory {path} was not found.");
}
var fileContents =
from FileName in files?.AsParallel()
let extension = Path.GetExtension(FileName)
where extension == ".txt" || extension == ".htm"
let Text = File.ReadAllText(FileName)
select new
{
Text,
FileName
};
try
{
foreach (var item in fileContents)
{
Console.WriteLine($"{Path.GetFileName(item.FileName)}:{item.Text.Length}");
count++;
}
}
catch (AggregateException ae)
{
ae.Handle(ex =>
{
if (ex is UnauthorizedAccessException uae)
{
Console.WriteLine(uae.Message);
return true;
}
return false;
});
}
Console.WriteLine($"FileIterationOne processed {count} files in {sw.ElapsedMilliseconds} milliseconds");
}
EnumerateFiles örneği
Bu örnekte, ağaçtaki tüm dizinlere erişiminiz olduğunda, dosya boyutları büyük olmadığında ve erişim süreleri önemli olmadığında basit senaryolarda dosya dizinleri üzerinde nasıl yineleme yapılacağını gösterir. Bu yaklaşım önceki örnekten daha hızlı sonuç üretmeye başlar.
public static void FileIterationTwo(string path) //225512 ms
{
var count = 0;
var sw = Stopwatch.StartNew();
var fileNames =
from dir in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
select dir;
var fileContents =
from FileName in fileNames.AsParallel()
let extension = Path.GetExtension(FileName)
where extension == ".txt" || extension == ".htm"
let Text = File.ReadAllText(FileName)
select new
{
Text,
FileName
};
try
{
foreach (var item in fileContents)
{
Console.WriteLine($"{Path.GetFileName(item.FileName)}:{item.Text.Length}");
count++;
}
}
catch (AggregateException ae)
{
ae.Handle(ex =>
{
if (ex is UnauthorizedAccessException uae)
{
Console.WriteLine(uae.Message);
return true;
}
return false;
});
}
Console.WriteLine($"FileIterationTwo processed {count} files in {sw.ElapsedMilliseconds} milliseconds");
}
kullanırken GetFiles, ağaçtaki tüm dizinler üzerinde yeterli izinlere sahip olduğunuzdan emin olun. Aksi takdirde, bir özel durum oluşturulur ve hiçbir sonuç döndürülür. bir PLINQ sorgusunda kullanırken EnumerateDirectories , G/Ç özel durumlarını yinelemeye devam edebilmenizi sağlayan düzgün bir şekilde işlemek sorunludur. Kodunuzun G/Ç veya yetkisiz erişim özel durumlarını işlemesi gerekiyorsa, Nasıl yapılır: Dosya Dizinlerini Paralel Sınıfla Yineleme başlığı altında açıklanan yaklaşımı dikkate almanız gerekir.
G/Ç gecikmesi bir sorunsa, örneğin ağ üzerinden dosya G/Ç ile ilgiliyse, TPL ve Geleneksel .NET Zaman Uyumsuz Programlama ve bu blog gönderisinde açıklanan zaman uyumsuz G/Ç tekniklerinden birini kullanmayı göz önünde bulundurun.