Как подождать до File.Exists?
У меня есть приложение, которое прослушивает файл *.log в выбранной папке. Я использовал FileSystemWatcher
.
Но есть проблема. Другое приложение, ответственное за создание этого файла, выполняет следующие шаги:
- Создайте файл *.gz
- Распакуйте его в txt файл (некоторое произвольное имя файла)
- Измените имя *.txt на правильное с расширением *.log.
И я не могу изменить это поведение.
Итак, я сделал 2 FileSystemWatcher
для *.gz и *.txt файлов. Зачем? Поскольку это приложение иногда не распаковывает gz файл и иногда не переименовывает txt файл в окончательный файл *.log.
FileSystemWatcher2
улавливает txt файл, затем (в большинстве случаев он переименовывается для входа в следующие 1000 мс). Мне нужно подождать некоторое время, чтобы проверить, существует ли файл txt (если нет, он, кажется, переименован в окончательный *.журнальный файл).
Вопрос в том, как проверить, существует ли файл без Thread.Sleep()
, чтобы предотвратить зависание пользовательского интерфейса?
Надеюсь, это ясно, если не я попытаюсь описать это лучше. Я думаю, что это сложная проблема.
Пример кода:
Наблюдатель за файлом gz:
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 }
}
}
Наблюдатель за txt файлом:
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
Фактически FileSystemWatcher Создал событие, вызванное в отдельном потоке самой .NET. Итак, в основном вам не нужно ничего делать. Ваш код в порядке, как есть.
Вот доказательство:
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
Вы можете использовать BackGroundWorker для мониторинга файловой системы - и не замораживать свой интерфейс пользователя
Ответ 3
Вы можете использовать сон без блокировки потока пользовательского интерфейса, вы, по сути, спятите отдельный поток.
public event EventHandler FileCreated;
public void CheckFileExists()
{
while(!File.Exists(""))
{
Thread.Sleep(1000);
}
FileCreated(this, new EventArgs());
}
Затем назовите это следующим образом:
Thread t = new Thread(CheckFileExists);
this.FileCreated += new EventHandler(somemethod);
t.Start();
public void SomeMethod(object sender, EventArgs e)
{
MessageBox.Show("File Created!");
}
Или, как упоминалось в другом посте, используйте BackGroundWorker
вместо отдельного потока, поместите код, который я упомянул в DoWork
, и прослушаем событие OnFinish
, но видя, что не так много работы для выполнения методы прекрасны.