CsvHelper throws System.ObjectDisposedException on second iteration

Advertisements

I’m trying to write a method that will read all the CSV files from inside a ZIP file as submitted as an IFormFile through an HttpRequest.

I’m using CsvHelper to read the files contents using this code:

using (var archiveStream = zip.OpenReadStream())
{
    using (var archive = new ZipArchive(archiveStream))
    {
        foreach (var entry in archive.Entries)
        {
            using (var entryStream = entry.Open())
            {
                using (TextReader reader = new StreamReader(entryStream))
                {
                    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
                    {
                        using (var dataReader = new CsvDataReader(csv))
                        {
                            while (dataReader.Read())
                            {
                                object[] values = new object[dataReader.FieldCount];
                                dataReader.GetValues(values);
                                // do stuff with object[]
                            }
                        }
                    }
                }
            }
        }
    }
}

However, on the second iteration of the foreach I get System.ObjectDisposedException: 'Cannot access a closed file.' when it gets to var dataReader = new CsvDataReader(csv).

It’s not clear to me which "file" it thinks is disposed. How can I keep this stream open throughout the full loop?

Possibly relevant information: This is running inside a Task<> launched from an ApiController.

>Solution :

  • This is running inside a Task<> launched from an ApiController.
  • Are you awaiting the task?
  • I am not

The request data will be automatically disposed by ASP.NET when the request processing will finish (i.e. when the action result will be executed and response will be send to the client), including the request body, resulting in the stream returned by IFormFile.OpenReadStream being disposed too. Since you are not awaiting the processing task the request processing can be finish before the task hence the exception.

You need either to await the task processing the stream or alternatively – download all the data (into memory or in some kind of temp file) and process it "offline" (either via task or some kind of background worker pipeline – see Background tasks with hosted services in ASP.NET Core, Quartz.NET, Hangfire).

Leave a ReplyCancel reply