Dieses Problem ist tatsächlich ein bisschen schwierig, es sei denn, der Problembereich hat sich erheblich verändert, seit ich das letzte Mal damit zu tun hatte.
Am einfachsten ist es, einfach zu versuchen, die Datei zu öffnen, das Ergebnis abzufangen IOException
und wenn die Datei gesperrt ist, wird sie in eine Warteschlange gestellt, um später überprüft zu werden. Sie können nicht einfach versuchen, jede eingehende Datei zu verarbeiten, denn es gibt alle möglichen Fälle, in denen mehrere Ereignisse für dieselbe Datei erzeugt werden. Stattdessen müssen Sie sie in eine Warteschlange einreihen und diese in regelmäßigen Abständen überprüfen.
Hier ist eine grundlegende Klassenvorlage, die Ihnen bei diesem Problem helfen sollte:
public class FileMonitor : IDisposable
{
private const int PollInterval = 5000;
private FileSystemWatcher watcher;
private HashSet<string> filesToProcess = new HashSet<string>();
private Timer fileTimer; // System.Threading.Timer
public FileMonitor(string path)
{
if (path == null)
throw new ArgumentNullException("path");
watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Created += new FileSystemEventHandler(FileCreated);
watcher.EnableRaisingEvents = true;
fileTimer = new Timer(new TimerCallback(ProcessFilesTimer),
null, PollInterval, Timeout.Infinite);
}
public void Dispose()
{
fileTimer.Dispose();
watcher.Dispose();
}
private void FileCreated(object source, FileSystemEventArgs e)
{
lock (filesToProcess)
{
filesToProcess.Add(e.FullPath);
}
}
private void ProcessFile(FileStream fs)
{
// Your code here...
}
private void ProcessFilesTimer(object state)
{
string[] currentFiles;
lock (filesToProcess)
{
currentFiles = filesToProcess.ToArray();
}
foreach (string fileName in currentFiles)
{
TryProcessFile(fileName);
}
fileTimer.Change(PollInterval, Timeout.Infinite);
}
private void TryProcessFile(string fileName)
{
FileStream fs = null;
try
{
FileInfo fi = new FileInfo(fileName);
fs = fi.OpenRead();
}
catch (IOException)
{
// Possibly log this error
return;
}
using (fs)
{
ProcessFile(fs);
}
lock (filesToProcess)
{
filesToProcess.Remove(fileName);
}
}
}
(Hinweis: Ich habe das hier aus dem Gedächtnis abgerufen, es könnte also nicht perfekt sein - lassen Sie mich wissen, wenn es fehlerhaft ist).