Файловые дескрипторы C # выпускаются слишком поздно при открытии файлов на удаленном хосте (по символической ссылке) - PullRequest
0 голосов
/ 19 июля 2011

Моя программа в основном выглядит следующим образом:

using(XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
{
    //a lot of reader.Read() to read through the file
}

Программа читает таким образом большое количество небольших файлов (обычно 5k в секунду), и на локальных машинах это работает правильно.Однако сейчас я пытаюсь передать ему входные данные с удаленного компьютера.Я создал символическую папку NTFS для удаленного хоста на моем локальном диске.Поэтому, когда моя машина обращается к C: \ MyFolder, она прозрачно обращается к \ NetworkComputer \ MySharedFolder.Пока все хорошо!

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

После некоторой дополнительной отладки я обнаружил следующее (с помощью проводника процессов).

При локальном запуске процесс начинается с 400 дескрипторов (вероятно, из-за .NET), а затем при нажатии кнопки запускакнопка количество дескрипторов быстро увеличивается до 600, затем уменьшается до 400, затем увеличивается до 600 и т. д. Это, вероятно, включается сборщик мусора, удерживая количество файловых дескрипторов вниз.Когда процесс завершает обработку файлов, количество дескрипторов файлов возвращается к 400.

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

TLDR: Так что это мой вопрос: Как можно избежать зависания файловых дескрипторовудаленный компьютер при обращении к нему по символической ссылке?

Редактировать:

Иногда появляется другое исключение (IOException) «Недостаточно серверного хранилища для обработки этой команды».Я не уверен, как противостоять этому, но я нашел некоторую дополнительную информацию, все еще не уверен, что это значит http://support.microsoft.com/kb/285089 http://support.microsoft.com/kb/106167

Edit2:

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

Я также нашел несколько статей, которые указывают, что увеличение размера IRPSstacks может помочь, однако, поскольку компьютер не находится под моим непосредственным контролем, это может оказаться невозможным.

Ответы [ 3 ]

2 голосов
/ 19 июля 2011

XmlReader автоматически закрывает / удаляет переданный поток?(то есть, FileStream вернулось из File.Open.)

Я не думаю, что это так, что объясняет, почему вы видите количество ручек, поднимающихся высоко, а затем падающих на ваш локальный компьютер.Дескрипторы не освобождаются до тех пор, пока GC не запустит финализаторы, а не когда каждый поток будет удален.

Попробуйте и посмотрите, имеет ли это какое-либо значение:

using (var fs = File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
using (var reader = XmlReader.Create(fs))
{
    // a lot of reader.Read() to read through the file
}
1 голос
/ 19 июля 2011

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

    using(FileStream steram = File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
    using (XmlReader reader = XmlReader.Create(steram))
    {
        //a lot of reader.Read() to read through the file
    }
0 голосов
/ 19 июля 2011

Я не уверен, происходит ли это из-за доступа к удаленной машине или из-за доступа по символической ссылке ...

Возможно, вы можете просто проверить поведение при доступе к удаленному компьютеру без символической ссылки - через UNC-путь и / или букву диска (smb mount) ...

Я не могу быть уверен на 100%, но я думаю, что символическая ссылка является частью проблемы ...

...