我已经在同一个类中设置了2个事件处理程序(让我们称之为WrapperClass
):一个用于将文件保存到文件夹,另一个用于将这些文件发送到web api。在应用程序主线程中,我在应用程序启动时调用了两个方法:
// save file to folder:
NewFileEventHandler();
// send file to api:
FileTransporter();
NewFileEventHandler
定义如下:
public void NewFileEventHandler()
{
SomeEventClass.NewFileEvent +=
new FileEventHandler(SaveFileToFolder);
}
private void SaveFileToFolder(File file)
{
FileHelper.SaveFileToFolder(file);
}
FileTransporter
定义如下,这是我遇到问题的地方:
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);
}
});
}
}
但是,行:
抛出异常:
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)
我不明白的是,由于lock
,可以使用此文件的唯一可能的两个进程是保存文件的线程和尝试将文件发送到api的线程。但是,我对FileSystemWatcher.Created
事件的理解是它在文件创建完成时触发。这意味着,保存文件的线程不应该在TransportFile()
方法尝试打开文件以将其发送到api时使用该文件。
有时文件夹中有多个文件(由于过去错过了电子邮件)。 IOException
只针对刚刚保存到文件夹的文件(换句话说,引发FileSystemWatcher.Created
事件的文件。文件夹中的其他文件按预期清除。有人可以帮忙吗?谢谢。
你在这里缺少一些东西:
FileCreated
。当文件由其他进程创建时,此事件被触发(可能不足为奇),而不是在其他进程写完文件时。这里发生的事情是,当其他进程仍在编写文件时,您的进程会收到通知,并且对其进行独占锁定。来自the documentation:创建文件后立即引发OnCreated事件。如果正在将文件复制或传输到监视目录中,则会立即引发OnCreated事件,然后是一个或多个OnChanged事件。
这里正确的做法是循环,直到你能够读取文件,如第二个答案中所述:Wait for file to be freed by process