2016-03-24 29 views
3

freigegeben wirdbenachrichtigt wird, wenn eine Dateisperre

Ich habe eine Kamera [C# und Windows als Plattform verwenden], die JPG-Dateien in einem lokalen Ordner in meinem PC schreibt. Ich möchte jede Datei laden, die die Kamera ablegt, also habe ich einen FileSystemWatcher, der mich benachrichtigt, wenn ein neues Bild erstellt wird, aber die Kamera sperrt die Datei, während es geschrieben wird, wenn ich versuche, es zu laden, gerade nachdem es benachrichtigt worden ist Bei seiner Erstellung bekomme ich eine Ausnahme, die besagt, dass die Datei gesperrt ist.

Derzeit habe ich eine while-Schleife (mit einem Thread.Sleep), die versucht, das Bild alle 0,2 Sekunden zu laden, aber es fühlt sich ein bisschen schmutzig an.

Gibt es eine elegantere Art zu warten, bis die Sperre aufgehoben wurde, damit ich die Datei laden kann, die sicher ist, dass sie nicht mehr benutzt wird?

+0

Mögliche Duplikate von [Wie Dateisperre überprüfen?] (Http://stackoverflow.com/questions/1304/how-to-check-for-file-lock) – Plutonix

+0

Ich will nicht wissen, ob es ist verschlossen. Ich möchte benachrichtigt werden, wenn es NICHT gesperrt ist. – SuperJMN

+2

werfen Sie einen Blick [https://social.msdn.microsoft.com/Forums/vstudio/en-US/dd1d86a8-b803-4425-bf84-db9a4b7c1d52/filesystemwatcher-for-locks-readwrite-lock-on-files?forum = csharpgeneral] (https://social.msdn.microsoft.com/Forums/vstudio/en-US/dd1d86a8-b803-4425-bf84-db9a4b7c1d52/filesystemwatcher-for-locks-readwrite-lock-on-files?forum= csharpgeneral) – esiprogrammer

Antwort

1

Sie werden nicht in Versuch und Irrtum umgehen können, d. H., Versuchen Sie, die Datei zu öffnen, IOException zu fangen, versuchen Sie es erneut. Sie können jedoch diese Hässlichkeit in einer separaten Klasse verstecken wie so:

public class CustomWatcher 
{ 
    private readonly FileSystemWatcher watcher; 
    public event EventHandler<FileSystemEventArgs> CreatedAndReleased; 

    public CustomWatcher(string path) 
    { 
     watcher = new FileSystemWatcher(path, "*.jpg"); 
     watcher.Created += OnFileCreated; 
     watcher.EnableRaisingEvents = true; 
    } 

    private void OnFileCreated(object sender, FileSystemEventArgs e) 
    { 
     // Running the loop on another thread. That means the event 
     // callback will be on the new thread. This can be omitted 
     // if it does not matter if you are blocking the current thread. 
     Task.Run(() => 
     { 
      // Obviously some sort of timeout could be useful here. 
      // Test until you can open the file, then trigger the CreeatedAndReleased event. 
      while (!CanOpen(e.FullPath)) 
      { 
       Thread.Sleep(200); 
      } 
      OnCreatedAndReleased(e); 
     }); 
    } 

    private void OnCreatedAndReleased(FileSystemEventArgs e) 
    { 
     CreatedAndReleased?.Invoke(this, e); 
    } 

    private static bool CanOpen(string file) 
    { 
     FileStream stream = null; 
     try 
     { 
      stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None); 
     } 
     catch (IOException) 
     { 
      return false; 
     } 
     finally 
     { 
      stream?.Close(); 
     } 
     return true; 
    } 
} 

Dieses „Beobachter“ kann wie folgt verwendet werden:

var watcher = new CustomWatcher("path"); 
watcher.CreatedAndReleased += (o,e) => 
{ 
    // Now, your watcher has managed to open and close the file, 
    // so the camera is done with it. Obviously, any other application 
    // is able to lock it before this code manages to open the file. 
    var stream = File.OpenRead(e.FullPath); 
} 

Haftungsausschluss: CustomWatcher braucht wahrscheinlich IDisposable und entsorgen die sein FileSystemWatcher entsprechend. Der Code zeigt lediglich ein Beispiel, wie die gewünschte Funktionalität erreicht werden kann.