2016-12-12 12 views
3

Я думаю, что это довольно очевидно в названии; Я хочу скопировать файл, не дожидаясь результата.Возможно ли «запустить» копию (большого) файла, не дожидаясь результата?

Functionaly Я хочу это:

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 !"); 
    } 

В основном мой основной поток освобождается через несколько миллисекунд. Я стараюсь сделать так:

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); 
      } 
     } 
    } 

Мой mytestfile.fil создается в моей папке, но ее размер 0kb.

С уважением,

+1

В основном вы должны будете дождаться завершения задачи (Task.Wait (...)). В противном случае консоль выйдет и завершит рабочий поток –

+1

Итак ... что не так с первым подходом (используя 'cmd.exe' и' Process.Start')? Если это то, что вы хотите, что с этим не работает для вас? –

+0

@samir Да, но я не хочу ждать ;-) – Florian

ответ

1

Ваш главный метод возвращает перед задачей завершения, поэтому приложение завершается.

5

В основном моя основная тема выпускается через несколько миллисекунд. Я стараюсь делать это так:

Вы должны как-то поддерживать процесс. Самый простой способ сделать это - если вы на самом деле нужно сделать копию файла на нить своей собственной - это выполнить ваш метод копирования на переднем плане резьбы:

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); 
      } 
     } 
    } 
} 

... или вы могли бы выполнить это в основном потоке, так как приложение не кажется, что-нибудь еще:

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); 
      } 
     } 
    } 
} 

Третий вариант, чтобы сделать ваш метод асинхр и ждать его завершения синхронно в главном методе:

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); 
      } 
     } 
    } 
} 

Обратите внимание, что вы не должны использовать асинхронный метод CopyToAsync, если вы его не ожидаете. Не смешивать синхронный и асинхронный код :)

+0

Я пробовал свой код, это то же самое ... файл создается, но не копируется. (0kb) – Florian

+0

Также Thread - это устаревший код, не используйте это! Я не знаю, почему это стоит! – mybirthname

+0

О, вы должны использовать синхронный метод CopyTo или ждать метода CopyToAsync. Я отредактировал свой ответ. – mm8

4

OK более одной ошибки.

  • Ваша программа завершает работу до завершения копирования. Вам нужно что-то вроде:
  • CopyToAsync не ждали

    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'' не '' async void'' –

+0

async void подходит для консольного приложения: http://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main -method-of-a-console-app. Также он может просто написать Task.Wait(), как упоминает Стивен Клири в комментариях. Я думаю, что этот ответ должен быть правильным. – mybirthname

+0

нормально протестировано и работает. также изменил async main, поэтому вам не нужна библиотека – Ewan

1

Похоже, что это может быть экземпляром XY problem.

Имейте в виду, что OS/рамки в основном дает ваш процесс свой собственный «пространство», чтобы запустить в, так что следующее:

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); 
     } 
    } 
} 

ничем не отличается с точки зрения производительности, чем просто делать

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

Поскольку ваше консольное приложение принципиально не делает ничего, кроме копирования файла, дополнительный поток просто добавляет дополнительные служебные данные.

Кроме того, если вы используете асинхронные операции внутри метода копирования, вы должны объявить метод async Task, а не void, потому что в противном случае вы не можете использовать ключевое слово await внутри метода Copy или подождать, пока метод Copy завершить в другом месте в коде. Итак:

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

Как написано, это имеет вопиющее состояние гонки и, вероятно, не будет работать правильно, потому что DestinationStream и SourceStream могут быть удалены до того SourceStream.CopyToAsync(DestinationStream) фактически закончена. Вам необходимо сделать

await SourceStream.CopyToAsync(DestinationStream); 

внутри вашего метода, чтобы предотвратить это.

Если вы запускаете операцию копирования с

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

вы уже эффективно работает это асинхронно с точки зрения программы, которая запустила его, так как программа, которая начала его не ждет процесса для завершения до его продолжения. Кстати, я полагаю, что это консольное приложение будет делать что-то другое, кроме запуска процесса, правильно? (Если нет, это кажется немного лишним).

+0

Да, конечно. Это просто, чтобы продемонстрировать, что я хочу – Florian

+0

Наконец, возможно, это не лучший способ сделать это. Может быть, я буду использовать систему очередей (MSMQueue или другую). – Florian

+0

@Florian Если вас интересует, что у меня есть образец кода [здесь] (http://stackoverflow.com/questions/41069723/transfer-data-from-windows-service-to-console-application-repeatedly/41071172 # 41071172) за то, что это стоит. – EJoshuaS