16

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

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

  1. 制作 *.gz 文件
  2. 解压成txt文件(随机文件名)
  3. 将 *.txt 名称更改为带有 *.log 扩展名的正确名称。

而且我无法改变这种行为。

所以我FileSystemWatcher为 *.gz 和 *.txt 文件制作了 2 s。为什么?因为这个app有时不会解压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

4 回答 4

16

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);
    }
}
于 2013-02-14T04:03:41.620 回答
3

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

于 2013-02-11T16:36:29.847 回答
3

您可以在不锁定 UI 线程的情况下使用睡眠,您实际上是在睡眠一个单独的线程。

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!");
}

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

于 2013-02-11T16:33:44.297 回答
0
int i = 0;
while (!File.Exists && i < 30) //limit the time to whait to 30 sec
{
    Threed.Sleep(1000);
    File.Refresh();
    i++;
}
于 2018-07-12T06:50:20.723 回答