6

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());
            }
        });
GrayFullBuster
  • 1,033
  • 3
  • 18
  • 23

2 Answers2

4

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

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

    // ...
}
maximpa
  • 1,958
  • 13
  • 16
2

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.

Community
  • 1
  • 1
Mike Parkhill
  • 5,511
  • 1
  • 28
  • 38
  • another application for creating the files., it could also be the more than one computer will use that application – GrayFullBuster Nov 23 '12 at 02:18
  • It is not possible to run it in directly no need to wait. and in creation of file is uniqure :) – GrayFullBuster Nov 23 '12 at 02:29
  • 1
    If it's not your own tasks fighting over the file then it must be the application that is creating it. It's possible that you'll pick up the file before the creator is finished writing it. If you wait a second (or less) it will probably become free so you can then grab it. – Mike Parkhill Nov 23 '12 at 14:44