2010-09-17 19 views
9

У меня есть программа, которая делает это грубо:Файл используется другим процессом

  1. открыть файл для чтения из него.
  2. закрыть файл
  3. Запустите файл, чтобы следить за изменениями в файле.
  4. Как только изменение обнаружено, флаг EnableRaisingEvents в FileWatcher установлен в ложь, и процесс повторяется с шага 1.

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

Ошибка я получаю:

необработанное исключение: System.IO.IOException: Процесс не может получить доступ к файлу «C: \ test.xml», так как он используется другим процессом.

Что-то не так? читатель с шага 1 моей программы все еще имеет открытый файл или какой-то совсем другой процесс, обращающийся к файлу, или это файл-файл по-прежнему смотрит файл после перехода к шагу 1 из 4, несмотря на то, что флаг установлен на false?

+0

Вы можете разместить свой код. Это может помочь нам ответить на ваш вопрос. – klabranche

+1

Опубликовать код. Помогите нам помочь вам. –

+1

Код очень большой и конфиденциальный, поскольку он предназначен для финансовой фирмы, но я посмотрю, смогу ли я сделать это безопасным и опубликовать его. – xbonez

ответ

8

Если ваш код похож на этот:

[STAThread] 
static void Main(string[] args) 
{ 
    string file = "temp.txt"; 
    ReadFile(file); 
    FileSystemWatcher fswatcher = new FileSystemWatcher(".\\"); 
    fswatcher.Changed += delegate(object sender, FileSystemEventArgs e) 
          { 
           ReadFile(e.FullPath); 
          }; 
    while (true) 
    { 
     fswatcher.WaitForChanged(WatcherChangeTypes.Changed); 
    } 
} 
private static void ReadFile(string file) 
{ 
    Stream stream = File.OpenRead(file); 
    StreamReader streamReader = new StreamReader(stream); 
    string str = streamReader.ReadToEnd(); 
    MessageBox.Show(str); 
    streamReader.Close(); 
    stream.Close(); 
} 

Если вы редактируете файл с помощью блокнота, а затем, когда вы нажмите кнопку «Сохранить», он откроет файл, а если вы просто закроете программу и нажмите «Сохранить» не делает. Я не знаю, является ли это ошибкой или недокументированной функцией блокнота, но это может быть вашей проблемой.Один из способов исправить это состоит в том, чтобы сделать следующее:

В своем анонимном делетете или в любом месте, где вы выполняете вызов, ReadFile() звоните Thread.Sleep(1000), чтобы программа ожидала, прежде чем читать файл, и ваш код должен работать нормально.

+1

Thread.Sleep, похоже, решил проблему. Благодаря! – xbonez

+0

@xbonez: этот код отлично работает для меня, даже без 'Thread.Sleep()'. (Я изменил 'MessageBox.Show' на' Console.WriteLine') Однако я все равно буду использовать инструкцию 'using'. – JohnB

+0

После того, как я сыграл еще немного, я обнаружил, что если у меня есть два экземпляра этой программы, просматривающих один и тот же файл, когда я нажимаю «Сохранить» в «Блокноте», я получаю эту ошибку от одного из экземпляров (другой продолжает работать): 'Этот процесс не может получить доступ к файлу 'c: \ file.txt', потому что он используется другим процессом. ' – JohnB

4

Вы можете использовать такой инструмент, как Process Explorer от http://www.sysinternals.com, чтобы видеть, кто имеет открытый дескриптор процесса

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

+0

+1 для процесса explorer. – NotMe

0

Есть много вещей, которые могут произойти.

Во-первых, убедитесь, что вы правильно распоряжаетесь файловым автором (закрытие не достаточно), используя предложение use во всем, что реализует IDisposable.

Во-вторых, вы просто читаете, убедитесь, что установлены флаги, установленные при открытии файла.

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

+0

+1: Согласен, используйте выражения 'using' – JohnB

3

Примечание: даже если в «Блокноте» открыт «file.txt», этот код по-прежнему работает, потому что он открывается для чтения.

using System; 
using System.IO; 

class Program 
{ 
    static void Main(string[] args) 
    { 
    ReadFromFile(@"C:\file.txt"); 
    Console.ReadLine(); 
    } 

    static void ReadFromFile(string filename) 
    { 
    string line; 
    using (StreamReader sr = File.OpenText(filename)) 
    { 
     line = sr.ReadLine(); 
     while (line != null) 
     { 
     Console.WriteLine(str); 
     line = sr.ReadLine(); 
     } 
     sr.Close(); 
    } 
    } 
} 

Или просто:

string text = System.IO.File.ReadAllText(@"C:\file.txt");

3

Наряду с другими ответами возможно, что когда FileWatcher реагирует на файл, он еще не закрыт этим приложением. На шаге 1 попытайтесь не сработать немедленно, но попробуйте несколько попыток с небольшой задержкой.

0

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

openfiles /query 

Также он позволяет отключать файлы, открытые пользователями сети.

openfiles /disconnect /id XXXX 

Если вы хотите использовать его для локального ПК, вы должны установить Поддерживайте Список объектов глобальный флаг:

openfiles /local on 

Следуйте link, чтобы получить более подробную информацию.

0

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

http://www.codeproject.com/Questions/461666/FileSystemWatcher-issue-in-windows-application Wait until file is unlocked in .NET

Смежные вопросы