如何等到File.Exists?

use*_*355 14 c# multithreading sleep file exists

我有一个应用程序,在所选文件夹中侦听*.log文件.我用过FileSystemWatcher.

但有一个问题.负责制作该文件的另一个应用程序采取以下步骤:

  1. 制作一个*.gz文件
  2. 将其解压缩到txt文件(一些随机文件名)
  3. 将*.txt名称更改为具有*.log扩展名的正确名称.

我无法改变这种行为.

所以我FileSystemWatcher为*.gz和*.txt文件做了2 秒.为什么?因为此应用程序有时不解压缩gz文件,有时不会将txt文件重命名为最终的*.log文件.

FileSystemWatcher2 捕获txt文件,然后(在大多数情况下,它被重命名为在接下来的1000毫秒登录)我需要等待一段时间来检查是否存在txt文件(如果没有,它似乎被重命名为最终的*.log文件).

问题是,如何检查文件是否存在而不Thread.Sleep()阻止UI冻结?

我希望很清楚,如果不是,我会尝试更好地描述它.我认为这是一个复杂的问题.

一些代码示例:

Watz for 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 }
   }
}
Run Code Online (Sandbox Code Playgroud)

Watger for 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
   }
}
Run Code Online (Sandbox Code Playgroud)

Bop*_*Bop 9

实际上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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*ley 3

您可以在不锁定 UI 线程的情况下使用 sleep,本质上是休眠一个单独的线程。

public event EventHandler FileCreated;
public void CheckFileExists()
{
  while(!File.Exists(""))
  {
    Thread.Sleep(1000); 
  }
  FileCreated(this, new EventArgs());
}
Run Code Online (Sandbox Code Playgroud)

然后将其称为:

Thread t = new Thread(CheckFileExists);
this.FileCreated += new EventHandler(somemethod);
t.Start();

public void SomeMethod(object sender, EventArgs e)
{
  MessageBox.Show("File Created!");
}
Run Code Online (Sandbox Code Playgroud)

或者正如另一篇文章中提到的,使用 aBackGroundWorker代替单独的线程,将我提到的代码放入DoWork并侦听OnFinish事件,但由于没有太多工作要做,这两种方法都可以。