How to wait until File.Exists?

29,448

Solution 1

Actually FileSystemWatcher Created event called in separate thread by .NET itself.. So basically you need to do absolutely nothing. Your code is OK as it is.

Here is the proof:

class Program
{
    static void Main(string[] args)
    {
        FileSystemWatcher fw = new FileSystemWatcher(@"C:\temp");
        fw.Created += fileSystemWatcher_Created;

        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

        fw.EnableRaisingEvents = true;

        Console.ReadLine();
    }

    static void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    }
}

Solution 2

You can use sleep without locking the UI thread, you essentially sleep a seperate thread.

public event EventHandler FileCreated;
public void CheckFileExists()
{
  while(!File.Exists(""))
  {
    Thread.Sleep(1000); 
  }
  FileCreated(this, new EventArgs());
}

Then call this as:

Thread t = new Thread(CheckFileExists);
this.FileCreated += new EventHandler(somemethod);
t.Start();

public void SomeMethod(object sender, EventArgs e)
{
  MessageBox.Show("File Created!");
}

Or as mentioned in another post use a BackGroundWorker in place of the seperate thread, put the code I mentioned into DoWork and listen for OnFinish event but seeing as there isn't that much work to do either methods are fine.

Solution 3

You can use a BackGroundWorker to monitor the file system - and avoid freezing your UI

Share:
29,448
user1750355
Author by

user1750355

Updated on July 12, 2020

Comments

  • user1750355
    user1750355 almost 4 years

    I have an app, listening for the *.log file in a chosen folder. I used FileSystemWatcher.

    But there is a problem. The other app responsible for making that file takes following steps:

    1. Make a *.gz file
    2. Unpack it to txt file (some random file name)
    3. Change the *.txt name to proper one with *.log extension.

    And I can not change this behaviour.

    So I made 2 FileSystemWatchers for *.gz, and *.txt files. Why? Because this app sometimes doesn't unpack the gz file, and sometimes doesn't rename the txt file to the final *.log file.

    FileSystemWatcher2 catches txt file, then (in the most cases it is renamed to log in the next 1000ms) I need to wait some time to check if txt file exists (if not, it seems to be renamed to the final *.log file).

    The question is, how to check if file exists without Thread.Sleep() to prevent UI freeze?

    I hope it is clear, if not I will try to describe it better. I think this is a complex problem.

    Some code sample:

    Watcher for gz file:

    private void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
    {
       //this is for gz files in case if gz file is not unpacked automatically by other app
       //I need to wait and check if gz was unpacked, if not, unpack it by myself,
       //then txt watcher will catch that
       Thread.Sleep(5000);
       if (File.Exists(e.FullPath))
       {
          try
          {
             byte[] dataBuffer = new byte[4096];
             using (System.IO.Stream fs = new FileStream(e.FullPath, 
                                                         FileMode.Open, 
                                                         FileAccess.Read))
             {
                using (GZipInputStream gzipStream = new GZipInputStream(fs))
                {                            
                   string fnOut = Path.Combine(path_to_watcher, 
                                               Path.GetFileNameWithoutExtension(e.FullPath));
    
                   using (FileStream fsOut = File.Create(fnOut))
                   {
                      StreamUtils.Copy(gzipStream, fsOut, dataBuffer);
                   }                            
                }
             }
          }
          catch { //Ignore }
       }
    }
    

    Watcher for txt file:

    private void fileSystemWatcher2_Created(object sender, FileSystemEventArgs e)
    {
       //this is for txt file
       Thread.Sleep(3500);
       if (File.Exists(e.FullPath))
       {
          //make my actions
       }
       else
       {
          //make my actions
       }
    }
    
  • CodingGorilla
    CodingGorilla over 11 years
    This is probably better handled by either a Task or ThreadPool.QueueUserWorkItem.
  • LukeHennerley
    LukeHennerley over 11 years
    @CodingGorilla Obviously this would be dependant on the OP framework for task, but yeah your probably right :P