Доступ к файлу, созданному отдельным потоком

#c# #multithreading #io #file-copying

#c# #многопоточность #io #копирование файла

Вопрос:

У меня проблема с многопоточностью при копировании и доступе к файлам.

У меня есть служба, которая загружает и распаковывает Zip-архив, затем копирует файл из распакованной папки в нужное место:

 //Download, and uzip archive...

//Copy a needed file to its right location
File.Copy(fileName, fileDestination);
 

Затем я запускаю отдельный поток, который должен получить доступ к скопированным файлам:

 TheadPool.QueueUserWorkItem(s => processCopiedFile(fileDestination));
 

Вот фрагмент кода из ProcessCopiedFile:

 private void ProcessCopiedFile(string filePath)
{
    ...
    //Load the file, previously copied here
    var xml = XDocument.Load(filePath);
    ...
    //Do other work...
}
 

XDoument.Сбой вызова Load с исключением:

 The process cannot access the file <FileName> because it is used by another process.
 

Похоже на файл.Копирование сохраняет файл результата заблокированным. Когда все работают синхронно, он работает без ошибок.
У вас есть какие-либо мысли?
Спасибо.

Ответ №1:

Файл.Копирование ничего не сохраняет открытым или заблокированным, это атомарная операция, которая требует некоторого времени, в зависимости, конечно, от дискового / сетевого ввода / вывода и размера файла.

Конечно, при переходе от синхронизации к асинхронности вы должны убедиться, что вы не обращаетесь к файлу назначения, пока копирование все еще выполняется.

Комментарии:

1. Сначала я вызываю File . Скопируйте (синхронно), затем я запускаю новый поток. Вызвать файл. Копирование вызывается синхронно, оно гарантированно завершает свою работу до запуска нового потока. Или я где-то ошибаюсь?

2. 1 — Просто для пояснения последней части: Windows сохраняет эксклюзивную блокировку файла во время его копирования.

Ответ №2:

Скопируйте файл с потоком, чтобы избежать блокировки Windows из File.Copy

 using(var s = new MemoryStream(File.ReadAllBytes(filePath))
{
    using(var fs = new FileStream(newLocation, FileMode.Create))
    {
        s.WriteTo(fs);
    }
}
 

Комментарии:

1. Правильное копирование файлов — это ракетостроение. Необходимо позаботиться о сохранении атрибутов файла и альтернативных потоков в файле. Не делайте этого самостоятельно.