问题
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:
- Make a *.gz file
- Unpack it to txt file (some random file name)
- Change the *.txt name to proper one with *.log extension.
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
}
}
回答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);
}
}
回答2:
You can use a BackGroundWorker to monitor the file system - and avoid freezing your UI
回答3:
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.
回答4:
int i = 0;
while (!File.Exists && i < 30) //limit the time to whait to 30 sec
{
Threed.Sleep(1000);
File.Refresh();
i++;
}
来源:https://stackoverflow.com/questions/14816425/how-to-wait-until-file-exists