Подождите, пока файл не будет разблокирован в .NET - PullRequest
87 голосов
/ 09 сентября 2008

Какой самый простой способ заблокировать поток, пока файл не будет разблокирован и доступен для чтения и переименования? Например, есть ли где-нибудь в .NET Framework метод WaitOnFile ()?

У меня есть служба, которая использует FileSystemWatcher для поиска файлов, которые должны быть переданы на FTP-сайт, но событие созданный файл запускается до того, как другой процесс завершит запись файла.

Идеальное решение будет иметь период ожидания, поэтому поток не будет зависать вечно, прежде чем сдаться.

Редактировать: После опробования некоторых из приведенных ниже решений я в итоге изменил систему , чтобы все файлы записывались в Path.GetTempFileName(), а затем выполнил File.Move() до конечного местоположения. Как только сработало событие FileSystemWatcher, файл уже был завершен.

Ответы [ 15 ]

0 голосов
/ 14 марта 2017

Возможным решением было бы объединение наблюдателя файловой системы с некоторым опросом,

получать уведомления за каждое изменение в файле, а при получении уведомления проверять, является ли оно заблокировано, как указано в принятом в настоящее время ответе: https://stackoverflow.com/a/50800/6754146 Код для открытия файлового потока скопирован из ответа и немного изменен:

public static void CheckFileLock(string directory, string filename, Func<Task> callBack)
{
    var watcher = new FileSystemWatcher(directory, filename);
    FileSystemEventHandler check = 
        async (sender, eArgs) =>
    {
        string fullPath = Path.Combine(directory, filename);
        try
        {
            // Attempt to open the file exclusively.
            using (FileStream fs = new FileStream(fullPath,
                    FileMode.Open, FileAccess.ReadWrite,
                    FileShare.None, 100))
            {
                fs.ReadByte();
                watcher.EnableRaisingEvents = false;
                // If we got this far the file is ready
            }
            watcher.Dispose();
            await callBack();
        }
        catch (IOException) { }
    };
    watcher.NotifyFilter = NotifyFilters.LastWrite;
    watcher.IncludeSubdirectories = false;
    watcher.EnableRaisingEvents = true;
    //Attach the checking to the changed method, 
    //on every change it gets checked once
    watcher.Changed += check;
    //Initially do a check for the case it is already released
    check(null, null);
}

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

0 голосов
/ 04 марта 2014

Я столкнулся с подобной проблемой при добавлении вложения Outlook. «Использование» спасло день.

string fileName = MessagingBLL.BuildPropertyAttachmentFileName(currProp);

                //create a temporary file to send as the attachment
                string pathString = Path.Combine(Path.GetTempPath(), fileName);

                //dirty trick to make sure locks are released on the file.
                using (System.IO.File.Create(pathString)) { }

                mailItem.Subject = MessagingBLL.PropertyAttachmentSubject;
                mailItem.Attachments.Add(pathString, Outlook.OlAttachmentType.olByValue, Type.Missing, Type.Missing);
0 голосов
/ 23 января 2013

Просто используйте событие Изменено с NotifyFilter NotifyFilters.LastWrite :

var watcher = new FileSystemWatcher {
      Path = @"c:\temp\test",
      Filter = "*.xml",
      NotifyFilter = NotifyFilters.LastWrite
};
watcher.Changed += watcher_Changed; 
watcher.EnableRaisingEvents = true;
0 голосов
/ 23 июля 2009

Как насчет этого в качестве опции:

private void WaitOnFile(string fileName)
{
    FileInfo fileInfo = new FileInfo(fileName);
    for (long size = -1; size != fileInfo.Length; fileInfo.Refresh())
    {
        size = fileInfo.Length;
        System.Threading.Thread.Sleep(1000);
    }
}

Конечно, если размер файла уже выделен при создании, вы получите ложное срабатывание.

0 голосов
/ 09 сентября 2008

Я делаю это так же, как Гульзар, просто продолжайте пробовать петлю.

На самом деле я даже не беспокоюсь о наблюдателе файловой системы. Опрос сетевого диска на наличие новых файлов раз в минуту - это дешево.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...