1

I'm occasionally seeing a System.ObjectDisposedException when trying to make a POST request with a StreamContent as the file type. I saw this once or twice last week, but was unable to repro, but a teammate is hitting this error consistently. Here's the code in question. I've simplified it a bit, but made sure to keep the same structure as the code that we have:

async Task ThisMethodThrows()
{
    string filePath = "foo.file";
    await ExecuteAndIgnoreFileInUseException(() =>
    {
        using (FileStream filestream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            return this.client.UploadFile(filestream);
        }
    });
}

// We have to do this a lot, so there's a common method to avoid needing to copy this bulky try-catch and HResult everywhere
static async Task ExecuteAndIgnoreFileInUseException(Func<Task> func)
{
    try
    {
        await func();
    }
    catch (Exception)
    {
        if (ex.HResult != -2146233088) // This HResult indicates file is in use
        {
            throw;
        }
    }
}

// Code in this.client from above:
private readonly HttpClient inner;

public Client()
{
    this.inner = new HttpClient();
    // other misc setup...
}

async Task UploadFile(Stream stream)
{
    using (HttpRequestMessage message = new HttpRequestMessage())
    {
        message.Method = HttpMethod.Post;
        message.Content = new StreamContent(stream);
        message.RequestUri = new Uri("http://foo.com/bar");

        HttpResponseMessage response = await this.inner.SendAsync(message);
        // error handling...
    }
}

We recently moved ThisMethodThrows and ExecuteAndIgnoreFileInUseException to use an asynchronous pattern since previously they were just using .Wait() on the async client methods, but now we're seeing what appears to be a race condition with the files and disposing and all that. My best guess right now is that the lambda function is returning the Task for this.client.UploadFile very quickly, and then the stream is getting disposed before the work is actually done. Do we need to make the lambda async and await that call within it to avoid this issue? What's the proper way to "async-ify" this code?

wlyles
  • 2,236
  • 1
  • 20
  • 38
  • 2
    `Do we need to make the lambda async and await that call within it to avoid this issue?` Well what happened when you tried doing that? Did it work, or not? – Servy Nov 06 '17 at 18:32
  • 2
    https://stackoverflow.com/questions/33722968/asynchronous-methods-in-using-statement – pm100 Nov 06 '17 at 18:32
  • You fileStream is disposed before client will finish the request. Add `await` before `this.client.UploadFile(filestream);` – Maxim Goncharuk Nov 06 '17 at 20:48

0 Answers0