2017-12-07 2 views
-2

Ich habe eine Basisklasse, die ich durchlaufen verwenden werden, um wenn Dateien und Verzeichnisse wie hier gezeigt:Abstract Class und Async, sollte ich eine neue Basisklasse erstellen?

public abstract class FileRecursionBase 
{ 
    protected DirectoryInfo Info; 

    protected FileRecursionBase(string sourceDirectory, string targetDirectory) 
    { 
     SetSourceDirectory(sourceDirectory); 
     TargetDirectory = targetDirectory; 
    } 

    private string _sourceDirectory; 

    protected string GetSourceDirectory() 
    { 
     return _sourceDirectory; 
    } 

    protected void SetSourceDirectory(string value) 
    { 
     _sourceDirectory = value; 
     Info = new DirectoryInfo(value); 
    } 

    protected string TargetDirectory { get; set; } 

    protected abstract void ProcessFile(FileInfo file); 
    protected abstract void ProcessDirectory(DirectoryInfo directory); 

    protected void EnumerateFiles() 
    { 
     foreach (var file in Info.EnumerateFiles()) 
     { 
      ProcessFile(file); 
     } 
    } 

    protected void EnumerateDirectories() 
    { 
     foreach (var directory in Info.EnumerateDirectories()) 
     { 
      ProcessDirectory(directory); 
     } 
    } 

    public virtual void Initialize() 
    { 
     EnumerateDirectories(); 
    } 
} 

Und der Einfachheit halber wollen wir eine einfache Zählklasse machen, dass diese Klasse

public class FileCounter : FileRecursionBase 
{ 
    protected ICounter Counter; 


    public FileCounter(string sourceDirectory, string targetDirectory, ICounter counter) : base(sourceDirectory, targetDirectory) 
    { 
     Counter = counter; 
    } 

    protected override void ProcessFile(FileInfo file) 
    { 
     Counter.Files++; 
     Counter.FileSize += file.Length; 
    } 

    protected override void ProcessDirectory(DirectoryInfo directory) 
    { 
     SetSourceDirectory(directory.FullName); 
     try 
     { 
      EnumerateFiles(); 
      EnumerateDirectories(); 
     } 
     catch (Exception) 
     { 
      //ignore 
     } 
    } 
} 

Die implementiert Die Klasse funktioniert wie beabsichtigt und wird rekursiv auf Grundlage der Methoden ProcessDirectory und ProcessFiles aufgelistet.

Was kann ich jedoch für Fälle tun, in denen ich ProcessFiles asynchron verarbeiten wollte? Da die abstrakte Klasse geschützte Methoden verwendet, kann ich auf eine Lücke bei der Initialisierung nicht warten.

Muss ich die gesamte Basisklasse ändern, um Aufgaben zu verwenden, selbst wenn die Klasse Kinder hat, die nicht asynchron sind?

Oder ist der richtige Weg, nur eine neue Basisklasse zu erstellen, die Aufgaben verwendet und den Großteil des Codes kopieren und einfügen? Ich sehe nur, ob jemand Ideen hat oder ob ich etwas übersehen habe.

+0

_ ".. Ich kann nicht auf eine Lücke warten .." _ - In diesem Fall ändern Sie Ihre Methodensignatur von 'void Foo (..)' zu 'async Task FooAsync (...)'. Das Umbenennen des tatsächlichen Methodennamens ist optional, aber es ist eine gute Übung, da es den Lesern im Voraus sagt, dass die Methode tatsächlich "asynchron" ist und dass es wahrscheinlich eine gute Idee ist, sie zu "erwarten". – MickyD

+0

@MickyD Das Problem dabei ist jedoch, dass nicht alle meine abgeleiteten Typen der Basisklasse asynchron sind. Wenn ich die Basisklasse in Task ändere, entsteht ein falscher Eindruck, dass die Methode in Klassen asynchron ist, die nicht von Natur aus asynchron sind. – Ambidex

+0

Dann zeigen Ihre abgeleiteten Typen an, ob sie async unterstützen (sagen wir eine Eigenschaft oder ein Feld); habe eine normale Methode und eine asynchrone Methode. Lassen Sie die Base die entsprechende Überschreibung aufrufen, abhängig davon, ob die Instanz asynchron ist oder nicht. – MickyD

Antwort

-1

Eigentlich auf den zweiten Gedanken, gibt es wirklich kein Szenario, in dem ich die Basismethoden asynchron machen müsste.

Ich kann einfach ProcessFile und ProcessDirectory async in der Kindklasse machen.

Die meisten asynchronen Tasks sind E/A-gebunden in der Natur, daher sollte der UI-Thread nicht gesperrt werden.

Wenn dies der Fall ist, würde ich nach bestem Verfahren den Blocking-Code in einer Task.Run aufrufen, da es an diesem Punkt CPU-gebundenen Code ist; Das Ändern der Basisklasse in Task-Methoden würde überhaupt nichts helfen, da es an diesem Punkt in einem separaten Thread ausgeführt wird.

Sorry, für die Verschwendung von Zeit.

+0

_ "Es gibt wirklich kein Szenario, in dem ich die Basismethoden asynchron machen müsste" _ - Ob die Basisklasse irrelevant ist, da sie keine Verarbeitung durchführt – MickyD

+0

Ihr vorletzter Absatz macht keinen Sinn – MickyD

+0

Ich bezog mich darauf Zu diesem Szenario sollte ich grundsätzlich eine Task.Run-Methode in einer Klasse nicht umbrechen, sondern diese Verantwortung dem Aufrufer selbst überlassen. https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html – Ambidex

Verwandte Themen