2013-02-11 6 views
10

Ich habe eine App, die auf die * .log-Datei in einem ausgewählten Ordner wartet. Ich habe FileSystemWatcher verwendet.Warten bis File.Exists?

Aber es gibt ein Problem. Die andere App verantwortlich für diese Datei zu machen nimmt wie folgt:

  1. Make a * .gz Datei
  2. es in txt-Datei Entpacken (einige zufällige Dateiname)
  3. Ändern der * .txt-Namen richtige ist mit * .log Erweiterung.

Und ich kann dieses Verhalten nicht ändern.

Also habe ich 2 FileSystemWatcher s für *. GZ und *. TXT-Dateien. Warum? Weil diese App manchmal die gz-Datei nicht entpackt und manchmal die txt-Datei nicht in die endgültige * .log-Datei umbenennt.

FileSystemWatcher2 fängt txt-Datei, dann (in den meisten Fällen ist es umbenannt, um die nächsten 1000ms einzuloggen) Ich muss einige Zeit warten, um zu überprüfen, ob TXT-Datei existiert (wenn nicht, scheint es in das endgültige umbenannt zu werden * .Logdatei).

Die Frage ist, wie überprüft werden kann, ob die Datei ohne Thread.Sleep() existiert, um das Einfrieren der Benutzeroberfläche zu verhindern?

Ich hoffe, es ist klar, wenn nicht, werde ich versuchen, es besser zu beschreiben. Ich denke, das ist ein komplexes Problem.

Einige Codebeispiel:

Watcher für gz-Datei:

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 für txt-Datei:

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

Alle 'Thread.Sleep()' tut, ist Relinquish den Faden lassen Sie die Computer-Ressourcen sie verwenden, so dass sie für andere Aufgaben verwendet werden können.Es ist nicht ideal für einige Szenarien (weil es eine minimale Granularität von 1 ms hat), aber für das, was Sie erreichen möchten, könnte es gut funktionieren. –

+0

@RobertHarvey Haben Sie Unterlagen dafür? Aus meiner Erfahrung beendet Thread.Sleep einen Thread von der Verarbeitung weiterer Anweisungen, bis die Zeit abgelaufen ist. Von MSDN: 'Der Thread wird vom Betriebssystem für die angegebene Zeit nicht zur Ausführung geplant. – CodingGorilla

+0

@CodingGorilla: Ja, das stimmt. Es blockiert und gibt die Ressourcen frei, die der Thread für andere Aufgaben bereithält. Es sagt im Grunde: "Ich mache nichts für die nächsten n Millisekunden, also könnt ihr während dieser Zeit etwas anderes machen." –

Antwort

1

Sie schlafen ohne Verriegelung des UI-Thread verwenden können, schlafen Sie im Wesentlichen ein seperater Thread.

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

Dann nennen dies als:

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

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

Oder wie es in einem anderen Beitrag erwähnt eine BackGroundWorker anstelle des separaten Thread verwenden, setzen Sie den Code, den ich in DoWork erwähnt und hören für OnFinish Ereignis aber da Es gibt nicht so viel Arbeit zu tun, beide Methoden sind in Ordnung.

+0

Dies wird wahrscheinlich besser durch eine 'Task' oder' ThreadPool.QueueUserWorkItem' behandelt. – CodingGorilla

+0

@CodingGorilla Offensichtlich wäre dies abhängig von der OP-Rahmen für die Aufgabe, aber ja, Sie haben wahrscheinlich Recht: P – LukeHennerley

+0

OK, vielen Dank für Ihre Ideen. Ich werde sie überprüfen. Es ist mega hilfreich – user1750355

3

können Sie eine BackGroundWorker verwenden, das Dateisystem zu überwachen - und verhindern, dass Ihre UI

7
Einfrieren

Eigentlich Filesystemwatcher Erstellt Ereignis in separaten Thread von .NET nannte sich .. Also im Grunde Sie absolut nichts zu tun brauchen . Ihr Code ist in Ordnung, wie es ist. Hier

ist der Beweis:

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