GrayFullBuster
GrayFullBuster

Reputation: 1063

File is being used by another process with FileSystemWatcher and Task

I have created an application that will watch a certain folder for only newly created files and list it in the listbox, now I want to do is everytime it will detect the file the application will read it and display the text on it in the listbox, I almost got because sometimes when it detects 2 or 3,4,5,6 etc files sometimes ok but sometimes also it will prompt error "The process cannot access the file 'C:\Users\PHWS13\Desktop\7.request.xml' because it is being used by another process.".

How to fix this? Here is my code:

private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
    {
        if (!listBox1.Items.Contains(e.FullPath))
        {
            //add path
            listBox1.Items.Add(e.FullPath + "" + DateTime.Now.ToString());
            //get the path
            path = e.FullPath;
            //start task
            startTask();
        }
    }

    private void startTask()
    {
        //start task
        Task t = Task.Factory.StartNew(runThis);
    }

    private void runThis()
    {
        //get the path
        string get_the_path = path;

        XDocument doc = XDocument.Load(get_the_path);
        var transac = from r in doc.Descendants("Transaction")
                      select new {
                          InvoiceNumber = r.Element("InvoiceNumber").Value,
                      };
        listBox2.Invoke((MethodInvoker)delegate() { 
            foreach(var r in transac){
                listBox2.Items.Add(r.ToString());
            }
        });

Upvotes: 6

Views: 2692

Answers (2)

maximpa
maximpa

Reputation: 1998

Try using XDocument.Load(Stream) with read-only options:

using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) 
{
    var doc = XDocument.Load(stream);

    // ...
}

Upvotes: 4

Mike Parkhill
Mike Parkhill

Reputation: 5551

You're sharing the path variable on all the tasks without locking. This means all your tasks could be trying to access the same file at the same time. You should be passing the path as a variable to startTask():

private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
    if (!listBox1.Items.Contains(e.FullPath))
    {
        //add path
        listBox1.Items.Add(e.FullPath + "" + DateTime.Now.ToString());

        //start task
        startTask(e.FullPath);
    }
}

private void startTask(string path)
{
    //start task
    Task t = Task.Factory.StartNew(() => runThis(path));
}

private void runThis(string path){}

EDIT: This thread: Is there a way to check if a file is in use? has a simple and ugly check for file access you could try that to test the file, if it fails then skip the file or wait and try again.

Upvotes: 2

Related Questions