How to check if a file is in use without throwing C #

16

I have an application that processes a file queue.

I need to open the files for reading and writing.

Sometimes the files are in use when I process them.

How can I check if the file is in use?

Today I deal more or less like this. I created a function:

public bool ArquivoEmUso(string caminhoArquivo)
{
    try
    {
        System.IO.FileStream fs = System.IO.File.OpenWrite(caminhoArquivo);
        fs.Close();
        return false;
    }
    catch (System.IO.IOException ex)
    {
        return true;
    }
}

And I use it like this:

if (ArquivoEmUso(@"C:\Teste.txt"))
{
    //Processar depois...
}
else
{
   //Processar agora....
}

It works by using try {} catch {}, but I'd like to prevent an exception from occurring.

Does anyone know of any way to test if the file is in use without having to throw an exception?

    
asked by anonymous 14.02.2014 / 18:08

2 answers

11

It's no use checking whether a file is in use in a competitive environment. Normally what you do is try to perform the desired operation, and put a try / catch around the operation with the file ... after all, just after checking, another external agent can switch to using the file. / p>

Explanation

When you do this:

if (!ArquivoEstaEmUso(nomeArquivo))
{
    // faz alguma operação com o arquivo
}

It's exactly the same as this:

var liberado = !ArquivoEstaEmUso(nomeArquivo);
if (liberado)
{
    // faz alguma operação com o arquivo
}

It turns out that an external agent can lock the file between the assignment of the variable and the if that comes next:

var liberado = !ArquivoEstaEmUso(nomeArquivo); // neste momento não está bloquado!
// o que acontece se o arquivo for bloqueado aqui... exatamente na posição deste comentário?
if (liberado)
{ ...

In a competitive environment, checking does not work, as the above can happen ... and then you would have to use a try / catch anyway.

How should your code look like

Even with the verification that you did in your code, one day it will fail, as I explained earlier.

I advise your code to look like this:

var caminhoArquivo = filaDeArquivos.Dequeue();
try
{
    using (System.IO.FileStream fs = System.IO.File.OpenWrite(caminhoArquivo))
    {
        // processar o arquivo agora
    }
}
catch
{
    // colocar o arquivo na fila, para ser processado depois
    filaDeArquivos.Enqueue(caminhoArquivo);
}

Where filaDeArquivos could be of type Queue<string> containing a list of the files you are going to process.

    
14.02.2014 / 18:16
6

According to answer of a similar question on stackoverflow.com the way is the same one you are using.

The answer still says that although many do not find it comfortable to use exceptions, for this task they are the way forward.

In any case, it is better to try to use the file because the only guarantee you will have that the file is not being used by another process is if you even get access to the lock while you gain access.

Otherwise, after checking the file, let's say it was not in use at the time you checked, who would ensure that in the next instant this was no longer valid?

    
14.02.2014 / 19:44