2016-12-12 2 views
3

Ich denke, es ist ziemlich offensichtlich im Titel; Ich möchte eine Datei kopieren, ohne auf das Ergebnis zu warten.Ist es möglich, eine Kopie einer (großen) Datei zu starten, ohne auf das Ergebnis zu warten?

functionaly möchte ich dies:

static void Main(string[] args) 
    { 
     string strCmdText = @"/C xcopy c:\users\florian\desktop\mytestfile.fil p:\"; 
     System.Diagnostics.Process.Start("CMD.exe", strCmdText); 
     Console.WriteLine("Finished !"); 
    } 

Grundsätzlich mein Haupt-Thread nach wenigen Millisekunden freigegeben wird. Ich versuche, wie dies zu tun:

static void Main(string[] args) 
    { 
     var t = Task.Run(() => Copy(@"c:\Users\florian\Desktop\mytestfile.fil", "p:")); 
    } 

    private static void Copy(string source, string destination) 
    { 
     using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
     { 
      using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
      { 
       SourceStream.CopyToAsync(DestinationStream); 
      } 
     } 
    } 

Mein mytestfile.fil in meinem Zielordner erstellt wird, aber seine Größe ist 0kb.

Grüße,

+1

In Ihrem Hauptfenster müssen Sie warten, bis die Aufgabe abgeschlossen ist (Task.Wait (...)). Andernfalls beendet die Konsole den Worker-Thread und beendet ihn. –

+1

Also ... was ist mit dem ersten Ansatz falsch (mit 'cmd.exe' und' Process.Start')? Wenn es das ist, was du willst, was ist dann mit dir nicht? –

+0

@samir Ja, aber ich will nicht warten ;-) – Florian

Antwort

1

Ihre Main-Methode kehrt vor der Aufgabe wurde erfolgreich abgeschlossen, so dass Ihre Anwendung beendet.

5

Grundsätzlich ist mein Haupt-Thread nach wenigen Millisekunden freigegeben. Ich versuche, so zu tun

Sie müssen den Prozess irgendwie am Leben erhalten. Der einfachste Weg, dies zu tun - wenn Sie tatsächlich die Dateikopie an einem Faden seines eigenen zu tun haben - ist Ihre Copy-Methode auf einen Vordergrund Thread ausgeführt:

class Program 
{ 
    static void Main(string[] args) 
    { 
     System.Threading.Thread thread = new System.Threading.Thread(()=> Copy(@"c:\Users\florian\Desktop\mytestfile.fil", "p:")); 
     thread.Start(); 
    } 

    private static void Copy(string source, string destination) 
    { 
     using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
     { 
      using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
      { 
       SourceStream.CopyTo(DestinationStream); 
      } 
     } 
    } 
} 

... oder Sie könnten ausführen auf dem Haupt-Thread, da Ihre Anwendung nicht alles anders scheinen:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string source = @"c:\Users\florian\Desktop\mytestfile.fil"; 
     string destination = "p"; 
     using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
     { 
      using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
      { 
       SourceStream.CopyTo(DestinationStream); 
      } 
     } 
    } 
} 

Eine dritte Möglichkeit ist Ihre Methode Asynchron zu machen und warten, bis es synchron im Hauptverfahren abzuschließen:

class Program 
{ 
    static void Main(string[] args) 
    { 
     CopyAsync(@"c:\Users\florian\Desktop\mytestfile.fil", "p:").Wait(); 
    } 

    private static async Task CopyAsync(string source, string destination) 
    { 
     using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
     { 
      using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
      { 
       await SourceStream.CopyToAsync(DestinationStream); 
      } 
     } 
    } 
} 

Beachten Sie, dass Sie die asynchrone CopyToAsync-Methode nicht verwenden sollten, wenn Sie nicht darauf warten. Nicht synchronen und asynchronen Code mischen :)

+0

Ich habe Ihren Code ausprobiert es ist das gleiche ... die Datei wird erstellt, aber nicht kopiert. (0kb) – Florian

+0

Auch Thread ist Legacy-Code nicht verwenden! Ich habe keine Ahnung, warum wurde upvoted! – mybirthname

+0

Oh, Sie müssen die synchrone CopyTo-Methode verwenden oder auf die CopyToAsync-Methode warten. Ich habe meine Antwort bearbeitet. – mm8

4

OK mehr als einen Fehler.

  • Ihr Programm wird beendet, bevor die Kopie abgeschlossen ist. Sie brauchen so etwas wie:
  • copyToAsync nicht

    class Program 
    { 
        private static void Main(string[] args) 
        { 
         var source = new CancellationTokenSource(); 
         Console.CancelKeyPress += (s, e) => 
         { 
          e.Cancel = true; 
          source.Cancel(); 
         }; 
    
        try 
        { 
         MainAsync(args, source.Token).GetAwaiter().GetResult(); 
         return; 
        } 
        catch (OperationCanceledException) 
        { 
         return; 
        } 
    } 
    
    static async Task MainAsync(string[] args, CancellationToken token) 
    { 
        var t = Task.Run(() => Copy(@"c:\test.txt", @"c:\dest\")); 
        Console.WriteLine("doing more stuff while copying"); 
        await t; 
        Console.WriteLine("Finished !"); 
    } 
    
    private static void Copy(string source, string destination) 
    { 
        using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
        { 
         using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
         { 
          SourceStream.CopyTo(DestinationStream); 
         } 
        } 
    } 
    

    }

+4

'' async Task'' nicht '' async void'' –

+0

async void ist für Konsolenanwendung in Ordnung: http://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main -Methode einer Konsolen-App Auch kann er einfach Task.Wait() schreiben wie Stephen Cleary in den Kommentaren erwähnen. Ich denke, diese Antwort sollte die richtige sein. – mybirthname

+0

ok getestet und funktioniert. änderte auch die async Hauptleitung, also benötigen Sie nicht eine Bibliothek – Ewan

1

Es scheint, erwartet wurde wie könnte dies eine Instanz des XY problem sein.

Beachten Sie, dass das OS/Rahmen im Allgemeinen Ihr Prozess wird unter Angabe der eigenen „Raum“ in laufen, so dass die folgenden:

static void Main(string[] args) 
{ 
    var t = Task.Run(() => Copy(@"c:\Users\florian\Desktop\mytestfile.fil", "p:")); 
} 

private static void Copy(string source, string destination) 
{ 
    using (FileStream SourceStream = File.Open(source, FileMode.Open)) 
    { 
     using (FileStream DestinationStream = File.Create(destination + source.Substring(source.LastIndexOf('\\')))) 
     { 
      SourceStream.CopyToAsync(DestinationStream); 
     } 
    } 
} 

ist nicht anders in Bezug auf die Leistung als nur

tun
static void Main(string[] args) 
{ 
    Copy(@"c:\Users\florian\Desktop\mytestfile.fil", "p:"); 
} 

Da Ihre Konsolenanwendung grundsätzlich nichts anderes tut als das Kopieren der Datei, fügt der zusätzliche Thread nur zusätzlichen Aufwand hinzu.

Auch, wenn Sie asynchrone Operationen innerhalb der Copy-Methode sind, sollen Sie Ihre Methode deklarieren async Task anstatt void denn sonst können Sie nicht das await Schlüsselwort innerhalb der Copy Methode verwenden oder warten, bis die Copy Methode an anderer Stelle zu vervollständigen in Code. Also:

private static async Task Copy(string source, string destination) 

Wie geschrieben, dies hat eine eklatante Racebedingung und wird wahrscheinlich nicht richtig funktionieren, weil DestinationStream und SourceStream können entsorgt werden, bevor SourceStream.CopyToAsync(DestinationStream) tatsächlich beendet. Sie müssen

await SourceStream.CopyToAsync(DestinationStream); 

innerhalb Ihrer Methode tun, um dies zu verhindern.

Wenn Sie den Kopiervorgang sind startet mit

System.Diagnostics.Process.Start(...); 

Sie bereits effektiv diese asynchron aus der Sicht des Programms ausgeführt wird, der es ins Leben gerufen, weil das Programm, das sie ins Leben gerufen nicht für den Prozess warten um abzuschließen, bevor es weitergeht. Ich gehe übrigens davon aus, dass diese Konsolenanwendung etwas anderes tut, als nur den Prozess zu starten, richtig? (Wenn nicht, scheint es ein wenig überflüssig).

+0

Ja natürlich. Es ist nur zu demonstrieren, was ich will – Florian

+0

Schließlich ist es vielleicht nicht der gute Weg, dies zu tun. Möglicherweise verwende ich ein Warteschlangensystem (MSMQueue oder andere). – Florian

+0

@Florian Wenn Sie daran interessiert sind, ich habe ein Codebeispiel [hier] (http://stackoverflow.com/questions/41069723/transfer-data-from-windows-service-to-console-application-repeatedly/41071172 # 41071172) für das, was es wert ist. – EJoshuaS

Verwandte Themen