Ich habe 2 Event-Handler beide innerhalb der gleichen Klasse deklariert (nennen wir es WrapperClass
): eine Datei in einen Ordner zu speichern und eine andere, um diese Dateien an eine Web-API zu senden. Bei der Anwendung Hauptthread, rief ich die beiden Methoden bei Anwendung Start-up:IOException passiert trotz Thread-Synchronisation C#
// save file to folder:
NewFileEventHandler();
// send file to api:
FileTransporter();
NewFileEventHandler
werden wie folgt definiert:
public void NewFileEventHandler()
{
SomeEventClass.NewFileEvent +=
new FileEventHandler(SaveFileToFolder);
}
private void SaveFileToFolder(File file)
{
FileHelper.SaveFileToFolder(file);
}
FileTransporter
wie unten definiert ist, das ist, wo ich bin immer mit der Frage:
public void FileTransporter()
{
FileSystemWatcher newFileWatcher = new FileSystemWatcher();
newFileWatcher.Path = ConfigurationHelper.applicationRootDirectory;
newFileWatcher.Filter = "*.txt";
newFileWatcher.Created +=
new FileSystemEventHandler(TransportFile);
newFileWatcher.EnableRaisingEvents = true;
}
And the `TransportFile()` is given below:
private void TransportFile(object source, FileSystemEventArgs e)
{
lock (_fileTransportLock)
{
string[] files = new string[] { };
files = Directory.GetFiles(ConfigurationHelper.applicationRootDirectory, "*.txt", SearchOption.TopDirectoryOnly);
Parallel.ForEach(files, (currentFile) =>
{
bool isHttpTransferSuccess = false;
isHttpTransferSuccess = FileHelper.SendFileToApi(userid, currentFile);
if (isHttpTransferSuccess)
{
File.Delete(currentFile);
}
});
}
}
jedoch die Zeile:
wirft die Ausnahme:
System.IO.IOException: The process cannot access the file 'C:\Users\myapp\file.txt' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.Open(String path, FileMode mode)
at FileHelper.SendFileToApi(String userId, String fileLocation)
Was ich nicht verstehe, ist, weil die lock
die einzig möglichen zwei Prozesse, die diese Datei verwenden können, sind der rote Faden, die Datei und der Faden ist das Speichern, die versucht, Sende die Datei an die API. Mein Verständnis des Ereignisses FileSystemWatcher.Created
ist jedoch, dass es ausgelöst wird, wenn die Erstellung der Datei abgeschlossen ist. Das bedeutet, dass der Thread, der die Datei speichert, die Datei nicht verwenden sollte, indem Sie versuchen, die Datei zu öffnen, um sie an api zu senden.
Manchmal befinden sich mehr als eine Datei im Ordner (wegen fehlender E-Mails in der Vergangenheit). Die IOException
wird nur für die Datei ausgelöst, die gerade in Ordner gespeichert wurde (mit anderen Worten, die Datei, die das Ereignis FileSystemWatcher.Created
ausgelöst hat. Die anderen Dateien im Ordner werden wie erwartet gelöscht. Kann jemand bitte helfen? Danke.
Oh, ich ... Danke für die Erklärung zu sehen. Der Grund, warum ich alle Dateien durchlaufe, wenn ich sicherstellen muss, dass die letzte Datei und alle anderen Dateien, die bei vorherigen Versuchen verpasst wurden, gelöscht werden. Danke für die Erklärung, ich werde daran arbeiten. – swdon
noch eine Sache, ist es in Ordnung, die Art, wie ich das Schloss benutze? Der Grund, warum ich diese Sperre gesetzt habe, ist, wenn mehrere Dateien erstellt wurden und mehr als ein Ereignis ausgelöst wurde. Ich wollte, dass das folgende Ereignis ausgelöst wird, nachdem das aktuelle Ereignis abgeschlossen wurde. – swdon
Die Sperre wird das verhindern, ja ... Es gibt möglicherweise bessere Möglichkeiten, dies zu tun, aber das wird funktionieren. –