How to wait until File.Exists?

user1750355 picture user1750355 · Feb 11, 2013 · Viewed 25.9k times · Source

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
   }
}

Answer

Boppity Bop picture Boppity Bop · Feb 14, 2013

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);
    }
}