2017-03-22 1 views
0

Je veux construire un service win (pas d'interface utilisateur) sur C# que tout ce qu'il fait est: exécuter sur la liste des répertoires et supprimer les fichiers qui plus de X kb. Je veux la meilleure performance,Quelle est la meilleure façon de supprimer le fichier avec condition

quelle est la meilleure façon de le faire? il n'y a pas de fonction async pur pour le fichier de suppression si je veux utiliser async attendre Je conclurai cette fonction comme:

public static class FileExtensions { 
    public static Task DeleteAsync(this FileInfo fi) { 
     return Task.Factory.StartNew(() => fi.Delete()); 
    } 
} 

et appel à cette fonction comme:

FileInfo fi = new FileInfo(fileName); 
await fi.DeleteAsync(); 

je pense à courir comme

foreach file on ListOfDirectories 
{ 

    if(file.Length>1000) 
     await file.DeleteAsync 

} 

mais cette option, les fichiers supprimer 1 par 1 (et tous les DeleteAsync utiliseront le fil de la Threadpool). donc je gagne pas du async, je peux le faire 1 par 1.

peut-être je pense que pour collecter les fichiers X sur la liste, puis de les supprimer AsParallel

s'il vous plaît aidez-moi à trouver la meilleure façon

+0

La première chose à optimiser serait de filtrer '.Length' * avant * itérer. – Filburt

+1

comme déjà dit Filburt, d'abord obtenir tous les fichiers dans une liste qui répondent à la condition, puis utilisez 'Parallel.ForEach' avec votre méthode de suppression. [MSDN] (https://msdn.microsoft.com/en-us/library/dd992001 (v = vs.110) .aspx) a un exemple –

+0

@MongZhu pourquoi? doyou voulez-vous que je vais sur tous les fichiers et mettre sur ListForDelete puis exécutez à nouveau et supprimer tous les fichiers de la liste? je ne comprends pas ce que vous avez dit et pourquoi – FADI1987

Répondre

1

Vous pouvez utiliser Directory.GetFiles("DirectoryPath").Where(x=> new FileInfo(x).Length < 1000); pour obtenir la liste des fichiers dont la taille est inférieure à 1 Ko.

Ensuite, utilisez Parallel.ForEach itérer sur cette collection comme ceci:

var collectionOfFiles = Directory.GetFiles("DirectoryPath") 
           .Where(x=> new FileInfo(x).Length < 1000); 

Parallel.ForEach(collectionOfFiles, File.Delete); 

On pourrait faire valoir que vous devez utiliser:

Parallel.ForEach(collectionOfFiles, currentFile => 
{ 
    File.Delete(currentFile); 
}); 

pour améliorer la lisibilité du code.

MSDN a un exemple simple sur la façon d'utiliser Parallel.ForEach()

Si vous vous interrogez sur l'objet FileInfo, voici the documentation

+0

Vous devez augmenter 'MaxDegreeOfParallelism', car celui par défaut est trop faible pour cette tâche (liée à l'E/S). – Evk

+0

@Evk Parallel.ForEach "envoyer" chaque suppression à un autre thread sur un autre code? que ce n'était pas le temps de prendre et libérer le fil à chaque fois? et le defualt n'est pas le nombre de core que j'ai? pourquoi ai-je besoin d'augmenter cela – FADI1987

+0

@ FADI1987 Je ne pense pas qu'il enverra chaque élément à un nouveau thread de pool de threads. Très probablement, il va partitionner vos articles en lots puis les exécuter sur des threads X. Mais vous voulez augmenter le nombre de threads car ce que vous faites est lié à l'E/S. Par défaut, le nombre de threads sera le nombre de cœurs et c'est bien quand le travail est lié au CPU (certains crunching de nombre). Dans votre cas, vous pouvez obtenir de meilleures performances si vous avez plus de threads que de cœurs de processeurs, car la plupart des threads seront simplement bloqués en attente de votre suppression et ne fonctionneront pas. – Evk

0

c'est peut-être peut vous aider.

public static class FileExtensions 
{ 
    public static Task<int> DeleteAsync(this IEnumerable<FileInfo> files) 
    { 
     var count = files.Count(); 
     Parallel.ForEach(files, (f) => 
     { 
      f.Delete(); 
     }); 
     return Task.FromResult(count); 
    } 
    public static async Task<int> DeleteAsync(this DirectoryInfo directory, Func<FileInfo, bool> predicate) 
    { 
     return await directory.EnumerateFiles().Where(predicate).DeleteAsync(); 
    } 
    public static async Task<int> DeleteAsync(this IEnumerable<FileInfo> files, Func<FileInfo, bool> predicate) 
    { 
     return await files.Where(predicate).DeleteAsync(); 
    } 

} 

enter image description here

enter image description here

 var _byte = 1; 
     var _kb = _byte * 1000; 
     var _mb = _kb * 1000; 
     var _gb = _mb * 1000; 
     DirectoryInfo d = new DirectoryInfo(@"C:\testDirectory"); 

     var deletedFileCount = await d.DeleteAsync(f => f.Length > _mb * 1); 
     Debug.WriteLine("{0} Files larger than 1 megabyte deleted", deletedFileCount); 
     // => 7 Files larger than 1 megabyte deleted 

     deletedFileCount = await d.GetFiles("*.*",SearchOption.AllDirectories) 
      .Where(f => f.Length > _kb * 10).DeleteAsync(); 

     Debug.WriteLine("{0} Files larger than 10 kilobytes deleted", deletedFileCount); 
     // => 11 Files larger than 10 kilobytes deleted