Reputation: 326
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:
And I can not change this behaviour.
So I made 2 FileSystemWatcher
s 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
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
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
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
Reputation: 19646
You can use a BackGroundWorker to monitor the file system - and avoid freezing your UI
Upvotes: 4