user1750355
user1750355

Reputation: 326

How to wait until File.Exists?

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

Upvotes: 17

Views: 35887

Answers (4)

Tamir Reiss
Tamir Reiss

Reputation: 1

int i = 0;
while (!File.Exists && i < 30) //limit the time to whait to 30 sec
{
    Threed.Sleep(1000);
    File.Refresh();
    i++;
}

Upvotes: 0

Boppity Bop
Boppity Bop

Reputation: 10463

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

Upvotes: 17

LukeHennerley
LukeHennerley

Reputation: 6434

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.

Upvotes: 4

Dave Bish
Dave Bish

Reputation: 19646

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

Upvotes: 4

Related Questions