Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

await population of a stream

In my MVC controller, i have an action that will populate a stream which i will use later:

[HttpPost]
public async Task<HttpResponseMessage> BuildFileContent(FileParameters fileParams)
{
    byte[] output;
    if (fileParams != null)
    {
        using (var stream = new MemoryStream())
        {
            await Task.Run(() => PopulateFile(fileParams, stream)); // Here i populate the stream
            stream.Flush();
            output = stream.ToArray();
        }
        var guid = Guid.NewGuid().ToString();
        FileContents.Add(guid, output); // just save the content for later use
        return this.Request.CreateResponse(HttpStatusCode.OK, new { Value = guid });
    }

    return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid parameters");
}

I had this problem because ReSharper is giving out a warning: access on disposed closure on the line PopulateFile(fileParams, stream) and pointing out stream.

I have searched for the meaning of it and it seems that it warns that i could possibly use an already disposed stream.

I want to await the population of the stream because the task could take long.

Is there a way that I can wait the population of the stream without ReSharper giving this warning? Moreover, i am calling stream inside the using clause, the stream should not yet be disposed until i call flush or the last line of the using clause is executed right? So why does ReSharper warn about accessing a disposed stream?

like image 658
raberana Avatar asked Dec 29 '13 04:12

raberana


1 Answers

Resharper warns you because you are using the stream inside a lambda expression that can basically be run whenever and not just inside the using scope.
If this was your code you could dispose of the stream before the task ended and you would have a ObjectDisposedException on your hands:

Task task = null;
using (var stream = new MemoryStream())
{
   task = Task.Run(() => PopulateFile(fileParams, stream)); // Here i populate the stream
   stream.Flush();
   output = stream.ToArray();
}
await task;

In your case however you await that operation and dispose the stream only after that operation has finished. So basically you are in the clear, but Resharper evidently doesn't know that.

To clear the warning altogether you can put the using scope inside the task:

await Task.Run(() => 
{
     using (var stream = new MemoryStream())
     {
         PopulateFile(fileParams, stream);
         stream.Flush();
         output = stream.ToArray();
     }
});

And I recommend you do.

like image 149
i3arnon Avatar answered Oct 03 '22 08:10

i3arnon