Hier ist eine Lösung, die für einige Benutzer übertrieben sein kann. Ich habe eine neue statische Klasse erstellt, die ein Ereignis enthält, das erst ausgelöst wird, wenn die Datei das Kopieren beendet hat.
Der Benutzer registriert Dateien, die er sich ansehen möchte, indem er FileAccessWatcher.RegisterWaitForFileAccess(filePath)
aufruft. Wenn die Datei nicht bereits überwacht wird, wird eine neue Aufgabe gestartet, die die Datei wiederholt überprüft, um zu sehen, ob sie geöffnet werden kann. Bei jeder Überprüfung liest es auch die Dateigröße. Wenn die Dateigröße nicht in einer vordefinierten Zeit (in meinem Beispiel 5 Minuten) zunimmt, wird die Schleife beendet.
Wenn die Schleife aus der Datei, auf die zugegriffen werden kann, oder von der Zeitüberschreitung beendet wird, wird das Ereignis FileFinishedCopying
ausgelöst.
public class FileAccessWatcher
{
// this list keeps track of files being watched
private static ConcurrentDictionary<string, FileAccessWatcher> watchedFiles = new ConcurrentDictionary<string, FileAccessWatcher>();
public static void RegisterWaitForFileAccess(string filePath)
{
// if the file is already being watched, don't do anything
if (watchedFiles.ContainsKey(filePath))
{
return;
}
// otherwise, start watching it
FileAccessWatcher accessWatcher = new FileAccessWatcher(filePath);
watchedFiles[filePath] = accessWatcher;
accessWatcher.StartWatching();
}
/// <summary>
/// Event triggered when the file is finished copying or when the file size has not increased in the last 5 minutes.
/// </summary>
public static event FileSystemEventHandler FileFinishedCopying;
private static readonly TimeSpan MaximumIdleTime = TimeSpan.FromMinutes(5);
private readonly FileInfo file;
private long lastFileSize = 0;
private DateTime timeOfLastFileSizeIncrease = DateTime.Now;
private FileAccessWatcher(string filePath)
{
this.file = new FileInfo(filePath);
}
private Task StartWatching()
{
return Task.Factory.StartNew(this.RunLoop);
}
private void RunLoop()
{
while (this.IsFileLocked())
{
long currentFileSize = this.GetFileSize();
if (currentFileSize > this.lastFileSize)
{
this.lastFileSize = currentFileSize;
this.timeOfLastFileSizeIncrease = DateTime.Now;
}
// if the file size has not increased for a pre-defined time limit, cancel
if (DateTime.Now - this.timeOfLastFileSizeIncrease > MaximumIdleTime)
{
break;
}
}
this.RemoveFromWatchedFiles();
this.RaiseFileFinishedCopyingEvent();
}
private void RemoveFromWatchedFiles()
{
FileAccessWatcher accessWatcher;
watchedFiles.TryRemove(this.file.FullName, out accessWatcher);
}
private void RaiseFileFinishedCopyingEvent()
{
FileFinishedCopying?.Invoke(this,
new FileSystemEventArgs(WatcherChangeTypes.Changed, this.file.FullName, this.file.Name));
}
private long GetFileSize()
{
return this.file.Length;
}
private bool IsFileLocked()
{
try
{
using (this.file.Open(FileMode.Open)) { }
}
catch (IOException e)
{
var errorCode = Marshal.GetHRForException(e) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}
return false;
}
}
Beispiel Nutzung:
// register the event
FileAccessWatcher.FileFinishedCopying += FileAccessWatcher_FileFinishedCopying;
// start monitoring the file (put this inside the OnChanged event handler of the FileSystemWatcher
FileAccessWatcher.RegisterWaitForFileAccess(fileSystemEventArgs.FullPath);
die FileFinishedCopyingEvent Griff:
private void FileAccessWatcher_FileFinishedCopying(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File finished copying: " + e.FullPath);
}
möglich Duplikat of [Gibt es eine Möglichkeit zu überprüfen, ob eine Datei verwendet wird?] (http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-isin- -use) –
Dieser Code hat einen einfachen Fehler mit 'File.Create (fileName)'. Die Antworten fehlen diesem Punkt. Es ist nicht notwendig auf die Schließung zu warten. – usr