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

Asked

Viewed 4,913 times

17

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 go to process them.

How can I check if the file is in use?

Today I treat 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....
}

Works using Try{} catch{}, but would like to avoid an exception.

Does anyone know any way to test whether the file is in use without an exception having to be made?

2 answers

12


There is no point in checking whether a file is in use in a competitive environment. Usually what is done is to try to perform the desired operation, and put a Try/catch around the operation with the file... after all, soon after checking, another external agent can switch to using the file.

Explanation

In doing so:

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

is 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 variable assignment and the if coming right after:

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 is no use, because the above can happen... and then you would have to use a Try/catch anyway.

How your code should look

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

I advise your code to stay that way:

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 like Queue<string> containing a list of the files you will process.

7

According to the reply of a similar question in stackoverflow.com the way is this 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.

Anyway, it is better to try using the file as the only guarantee you will have that the file is not being used by another process is if you even get access while locking it while getting access.

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.