0

While this particular question is about embeddedIO and FileReponseAsync but it probably has more to do with the handling of streams and async in Tasks in C#.

I am using EmbeddedIO (I needed a quick and dirty web server, and so far it has worked like a charm -- however the lack of documentation is a bit frustrating), but I am attempting to return a file with the following code:

  var file = new FileInfo(Path.Combine(FileLocations.TemplatePath, templateFile.FilePath));
  string fileExtension = Path.GetExtension(templateFile.FilePath);

  return this.FileResponseAsync(file, MimeTypes.DefaultMimeTypes.Value.ContainsKey(fileExtension) ? 
    MimeTypes.DefaultMimeTypes.Value[fileExtension] : "application/octet-stream");

I get the following error:

Message
Failing module name: Web API Module
Cannot access a closed file.
Stack Trace
at System.IO.__Error.FileNotOpen()

Which makes sense, since in the EmbedIO code FileResponseAsync looks like:

using (FileStream fileStream = file.OpenRead())
    return context.BinaryResponseAsync(fileStream, ct, useGzip);

and the filestream will be disposed as soon as the BinaryReponse returns. I've solved the problem by changing my code to not dispose of the filestream:

var fileStream = file.OpenRead();
return this.BinaryResponseAsync(fileStream);

While this works, it seems wrong to rely on Garbage Collection to dispose of these files at a later date. How are resources like this (not only in EmbeddedIO but in this modern async world) supposed to be handled?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Kris Erickson
  • 33,454
  • 26
  • 120
  • 175
  • Since `BinaryResponseAsync` takes ownership of a stream it is expected to dispose the stream when the method is no longer needs that stream. I don't see why you believe that code would be relying on GC to dispose stream... (Has absolutely nothing to do with async - synchronous versions of ActionResult that take stream bahave the same way as reading from the stream is happening way after returning such result) – Alexei Levenkov Feb 02 '19 at 17:57
  • @AlexeiLevenkov I looked at the code for WriteToOutputStream (https://github.com/unosquare/embedio/blob/master/src/Unosquare.Labs.EmbedIO/Extensions.Response.cs line ~289) which is what eventually gets called, and nothing disposes of the stream there. – Kris Erickson Feb 02 '19 at 18:16
  • Sorry... that looked very much like regular ASP.Net MVC code and I assumed those are just similar to ActionResult... Indeed `BinaryResponseAsync` is simply async function that must be `await`ed before you dispose stream - so `return await context.BinaryResponseAsync(fileStream, ct, useGzip);` should work (notice `await`. – Alexei Levenkov Feb 03 '19 at 23:17

0 Answers0