尽管线程同步C#发生IOException

问题描述 投票:0回答:1

我已经在同一个类中设置了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事件的文件。文件夹中的其他文件按预期清除。有人可以帮忙吗?谢谢。

c# multithreading locking ioexception
1个回答
3
投票

你在这里缺少一些东西:

  1. 你正在挂钩的事件是FileCreated。当文件由其他进程创建时,此事件被触发(可能不足为奇),而不是在其他进程写完文件时。这里发生的事情是,当其他进程仍在编写文件时,您的进程会收到通知,并且对其进行独占锁定。来自the documentation

创建文件后立即引发OnCreated事件。如果正在将文件复制或传输到监视目录中,则会立即引发OnCreated事件,然后是一个或多个OnChanged事件。

  1. 创建文件后,循环遍历目录中的所有文件(不仅仅是刚刚创建的文件)并传输所有文件。如果创建了多个文件,则对事件的第一次调用将尝试访问目录中的任何文件(实际上是并行),因此即使1)不是问题,也可能在此处与另一个文件发生冲突在处理第一个事件时被写入。

这里正确的做法是循环,直到你能够读取文件,如第二个答案中所述:Wait for file to be freed by process

© www.soinside.com 2019 - 2024. All rights reserved.