Асинхронный File Copy / Move в C #

голоса
47

Что такое правильный способ сделать копию файла / перемещать асинхронно в C #?

Задан 19/05/2009 в 14:14
источник пользователем
На других языках...                            


9 ответов

голоса
-1

Правильный способ копирования: использовать отдельный поток.

Вот как вы могли бы делать это (синхронно):

//.. [code]
doFileCopy();
// .. [more code]

Вот как сделать это асинхронно:

// .. [code]
new System.Threading.Thread(doFileCopy).Start();
// .. [more code]

Это очень наивный способ делать вещи. Совершено хорошо, решение будет включать в себя какой-либо метод события / делегата сообщать о состоянии копирования файлов, и уведомляет важные события, как отказ, завершение и т.д.

веселит, JRH

Ответил 19/05/2009 в 14:20
источник пользователем

голоса
6

Вы можете использовать асинхронные делегаты

public class AsyncFileCopier
    {
        public delegate void FileCopyDelegate(string sourceFile, string destFile);

        public static void AsynFileCopy(string sourceFile, string destFile)
        {
            FileCopyDelegate del = new FileCopyDelegate(FileCopy);
            IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null);
        }

        public static void FileCopy(string sourceFile, string destFile)
        { 
            // Code to copy the file
        }

        public static void CallBackAfterFileCopied(IAsyncResult result)
        {
            // Code to be run after file copy is done
        }
    }

Вы можете назвать это как:

AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt");

Эта ссылка говорит вам различные методы кодирования ASYN

Ответил 19/05/2009 в 14:34
источник пользователем

голоса
5

Вы можете сделать это , как эта статья предложила:

public static void CopyStreamToStream(
    Stream source, Stream destination,
    Action<Stream, Stream, Exception> completed)
    {
        byte[] buffer = new byte[0x1000];
        AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);

        Action<Exception> done = e =>
        {
            if(completed != null) asyncOp.Post(delegate
                {
                    completed(source, destination, e);
                }, null);
        };

        AsyncCallback rc = null;
        rc = readResult =>
        {
            try
            {
                int read = source.EndRead(readResult);
                if(read > 0)
                {
                    destination.BeginWrite(buffer, 0, read, writeResult =>
                    {
                        try
                        {
                            destination.EndWrite(writeResult);
                            source.BeginRead(
                                buffer, 0, buffer.Length, rc, null);
                        }
                        catch(Exception exc) { done(exc); }
                    }, null);
                }
                else done(null);
            }
            catch(Exception exc) { done(exc); }
        };

        source.BeginRead(buffer, 0, buffer.Length, rc, null);
Ответил 19/05/2009 в 14:42
источник пользователем

голоса
2

AFAIK, нет высокого уровня асинхронной API , чтобы скопировать файл. Тем не менее, вы можете создать свой собственный API для выполнения этой задачи с помощью Stream.BeginRead/EndReadи Stream.BeginWrite/EndWriteAPI - интерфейсов. Кроме того , вы можете использовать BeginInvoke/EndInvokeметод , как указано в ответах здесь, но вы должны иметь в виду, что они не будут не блокирование асинхронного ввода / вывода. Они просто выполняют задачу в отдельном потоке.

Ответил 02/09/2011 в 23:22
источник пользователем

голоса
-2

Я хотел бы предложить, что функция копирования файлов IO, доступен на языках программирования .Net, асинхронная в любом случае. После использования его в моей программе, чтобы переместить маленькие файлы, кажется, что последующие инструкции начинают выполняться до фактического копирование файлов завершено. Я Гуссинг, что исполняемый файл дает Windows На задачу, чтобы сделать копию, а затем сразу же возвращается, чтобы выполнить следующую команду - не дожидаясь Windows, чтобы закончить. Это заставляет меня построить в то время как петля только после вызова для копирования, который будет выполняться, пока я не могу подтвердить копирование завершено.

Ответил 30/07/2012 в 15:47
источник пользователем

голоса
35

Идея асинхронного программирования, чтобы вызывающий поток (если это пул потоки нити), чтобы вернуться в пул потоков для использования на какой-либо другой задаче, а асинхронная IO завершает. Под капотом контекст вызова забивается в структуру данных и 1 или более IO завершение нити контроля ожидания вызова для завершения. Когда IO завершает завершение поток вызывает обратно на пул потоков, восстанавливая контекст вызова. Таким образом, вместо 100 нитей блокирующих есть только нити завершающие и несколько нитей пула потоков, сидя вокруг в основном простаивает.

Лучшее, что я могу придумать это:

public async Task CopyFileAsync(string sourcePath, string destinationPath)
{
  using (Stream source = File.Open(sourcePath))
  {
    using(Stream destination = File.Create(destinationPath))
    {
      await source.CopyToAsync(destination);
    }
  }
}

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

жду делает то, что я описываю за кулисами. Если вы хотите, чтобы получить общее представление о том, как она работает, что, вероятно, поможет понять AsyncEnumerator Джеффа Рихтера. Они не могут быть полностью той же линии для линии, но идеи очень близки. Если вы когда-нибудь взглянуть на стек вызовов от метода «асинхронным» вы увидите MoveNext на нем.

Насколько движение идет не нужно быть асинхронной, если это действительно «Move», а не копия затем удалить. Перемещение является быстрой атомарной операцией против таблицы файлов. Он работает только так, хотя, если вы не пытаетесь переместить файл в другой раздел.

Ответил 10/05/2013 в 03:22
источник пользователем

голоса
16

Вот метод копирования асинхронного файла, который дает подсказки ОС, что мы читать и писать последовательно, так что он может заранее получить данные на чтении и есть вещи, готовые для записи:

public static async Task CopyFileAsync(string sourceFile, string destinationFile)
{
    using (var sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
    using (var destinationStream = new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
        await sourceStream.CopyToAsync(destinationStream);
}

Вы можете экспериментировать с размером буфера, а также. Вот это 4096 байт.

Ответил 17/02/2016 в 20:51
источник пользователем

голоса
8

Я расширение код, @DrewNoakes слегка (производительность и аннулирование):

  public static async Task CopyFileAsync(string sourceFile, string destinationFile, CancellationToken cancellationToken)
  {
     var fileOptions = FileOptions.Asynchronous | FileOptions.SequentialScan;
     var bufferSize = 4096;

     using (var sourceStream = 
           new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, fileOptions))

     using (var destinationStream = 
           new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize, fileOptions))

        await sourceStream.CopyToAsync(destinationStream, bufferSize, cancellationToken)
                                   .ConfigureAwait(continueOnCapturedContext: false);
  }
Ответил 28/04/2016 в 21:27
источник пользователем

голоса
4

Хотя есть некоторые обстоятельства , при которых вы хотите избежать Task.Run, Task.Run(() => File.Move(source, dest)будет работать. Стоит учесть , что когда файл просто перемещается в том же диске / томе, это почти мгновенная операция, так как заголовки изменяются , но содержимое файла не перемещаются. Различная «чистая» метода неизменно асинхронная скопировать поток, даже тогда , когда нет необходимости делать это, и в результате может быть совсем немного медленнее на практике.

Ответил 04/08/2016 в 01:55
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more