简体   繁体   中英

Windows Service Filestream giving System.IO.IOException: The process cannot access the file "filename" because it is being used by another process

I've got a windows service that I have to modify. Current code is this:

 public IRecord2 GetRecord(string name)
 {
      string path = Path.Combine(this.DirectoryPath, name);
      if (!File.Exists(path))
          return null;
      byte[] contents;
      lock (locker)   {
            using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize:4096, useAsync:true)) //WHERE THE PROBLEM IS OCCURRING
            {
                using (BinaryReader br = new BinaryReader(fs))
                {
                    contents = br.ReadBytes((int)fs.Length);
                    br.Close(); //unnecessary but threw it in just to be sure
                    fs.Close(); //unnecessary but threw it in just to be sure
                }
            }
            
        }
     return new Record2()
        {
            Name = name,
            Contents = contents
        };
}

Code that calls the function:

 public void Process(string pickupFileName)
    {
        string uniqueId = DateTime.Now.ToString("(yyyy-MM-dd_HH-mm-ss)");
        string exportFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + ".csv";
        string archiveFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + Path.GetExtension(pickupFileName);
        string unprocessedFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + Path.GetExtension(pickupFileName);

        try
        {
            _logger.LogInfo(String.Format("Processing lockbox file '{0}'", pickupFileName));

            IRecord2 record = _pickup.GetRecord(pickupFileName);
            if (record == null)
                return;

            _archive.AddOrUpdate(new Record2() { Name = archiveFileName, Contents = record.Contents });

            string pickupFileContents = UTF8Encoding.UTF8.GetString(record.Contents);

            IBai2Document document = Bai2Document.CreateFromString(pickupFileContents);
            StringBuilder sb = Export(document);

            _export.AddOrUpdate(new Record2() { Name = exportFileName, Contents = Encoding.ASCII.GetBytes(sb.ToString()) });

            _pickup.Delete(pickupFileName);
        }
        catch(Exception ex)
        {
            throw ex;
        }
    }

Function that calls Process:

public void Process()
    {
        foreach (ConfigFolderPath configFolderPath in _configSettings.ConfigFolderPaths)
        {
            IRecordRepository pickup = new FileRepository(configFolderPath.PickupFolderPath);
            IRecordRepository export = new FileRepository(configFolderPath.ExportFolderPath);
            IRecordRepository archive = new FileRepository(configFolderPath.ArchiveFolderPath);
            IRecordRepository unprocessed = new FileRepository(configFolderPath.UnprocessedFolderPath);

            Converter converter = new Converter(Logger,pickup, export, archive, unprocessed);
            
            foreach (string fileName in pickup.GetNames())
            {
                if (_configSettings.SupportedFileExtensions.Count > 0 && !_configSettings.SupportedFileExtensions.Any(extension => extension.ToLower() == Path.GetExtension(fileName).ToLower()))
                    continue;

                Action action = () => converter.Process(fileName);
                _queue.TryEnqueue(action, new WorkTicket() { Description = String.Format("Processing '{0}'", fileName), SequentialExecutionGroup = fileName });
            }
        }
    }

When 1 file is sent to the service, it processes and reads the file correctly. However, if two files are sent (difference of 3 minutes), the first file will process correctly, but the second will give me "System.IO.IOException: The process cannot access the file "filename" because it is being used by another process.

Is the solution to use a mutex as per https://stackoverflow.com/a/29941548/4263285 or is there a better solution to solve this?

Edit: More context:

Service is constantly running - as soon as files are dropped into a folder, it begins the process.

  1. get the file data (function up above)
  2. take the data, transform it, and put it into a different file
  3. Delete the original file from the one up above

rinse and repeat if more files

if one file is placed in the folder, it works correctly. if two files are placed in the folder, it breaks on the second file if service is stopped and restarted, it works again

In your code add ".Close()" here, at the end of the line:

using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize:4096, useAsync:true).Close())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM