如何等到File.Exists?

时间:2013-02-11 16:30:22

标签: c# multithreading file sleep exists

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

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

  1. 制作* .gz文件
  2. 将其解压缩为txt文件(一些随机文件名)
  3. 将* .txt名称更改为具有* .log扩展名的正确名称。
  4. 我无法改变这种行为。

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

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

    问题是,如何在没有Thread.Sleep()的情况下检查文件是否存在以防止UI冻结?

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

    一些代码示例:

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

4 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:3)

您可以使用BackGroundWorker来监控文件系统 - 并避免冻结您的用户界面

答案 2 :(得分:2)

你可以在不锁定UI线程的情况下使用sleep,你基本上可以睡一个单独的线程。

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事件,但是看不到做任何一种方法的工作都很好。

答案 3 :(得分:0)

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