10

I was using a method like below on the previous versions of WCF Web API:

// grab the posted stream
Stream stream = request.Content.ContentReadStream;

// write it to   
using (FileStream fileStream = File.Create(fullFileName, (int)stream.Length)) {

    byte[] bytesInStream = new byte[stream.Length];
    stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
    fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}

But on the preview 6, HttpRequestMessage.Content.ContentReadStream property is gone. I believe that it now should look like this one:

// grab the posted stream
System.Threading.Tasks.Task<Stream> stream = request.Content.ReadAsStreamAsync();

But I couldn't figure out what the rest of the code should be like inside the using statement. Can anyone provide me a way of doing it?

tugberk
  • 57,477
  • 67
  • 243
  • 335
  • 1
    not knowing anything about the web API, the quick and dirty approach would be `Stream stream = request.Content.ReadAsStreamAsync().Result` and then as before... – Jon Dec 06 '11 at 12:42
  • @Jon looks like it will work. can you provide the best approach here as well? – tugberk Dec 06 '11 at 12:44
  • I am assuming this was posted before `async` and `await`. – Jordan Oct 22 '15 at 19:12

3 Answers3

10

You might have to adjust this depending on what code is happening before/after, and there's no error handling, but something like this:

Task task = request.Content.ReadAsStreamAsync().ContinueWith(t =>
{
    var stream = t.Result;
    using (FileStream fileStream = File.Create(fullFileName, (int) stream.Length)) 
    {
        byte[] bytesInStream = new byte[stream.Length];
        stream.Read(bytesInStream, 0, (int) bytesInStream.Length);
        fileStream.Write(bytesInStream, 0, bytesInStream.Length);
    }
});

If, later in your code, you need to ensure that this has completed, you can call task.Wait() and it will block until this has completed (or thrown an exception).

I highly recommend Stephen Toub's Patterns of Parallel Programming to get up to speed on some of the new async patterns (tasks, data parallelism etc) in .NET 4.

Jon
  • 16,212
  • 8
  • 50
  • 62
  • Ok, this is good. You also said that I can use `task.Wait()` to ensure that the task is completed. Any change that I can reference a callback function here? If so, can you give an example if I am not asking too much. What I do after this code is to work on the uploaded file. since the task is not completed, I got **System.IO.FileNotFoundException** :s – tugberk Dec 06 '11 at 13:12
  • I've added an example using `async` and `await`. It really simplifies the code. – Jordan Oct 22 '15 at 19:19
9

Quick and dirty fix:

// grab the posted stream
Task<Stream> streamTask = request.Content.ReadAsStreamAsync();
Stream stream = streamTask.Result; //blocks until Task is completed

Be aware that the fact that the sync version has been removed from the API suggests that you should really be attempting to learn the new async paradigms to avoid gobbling up many threads under high load.

You could for instance:

streamTask.ContinueWith( _ => {
    var stream = streamTask.Result; //result already available, so no blocking
    //work with stream here
} )

or with new async await features:

//async wait until task is complete
var stream = await request.Content.ReadAsStreamAsync(); 

Take time to learn async/await. It's pretty handy.

spender
  • 117,338
  • 33
  • 229
  • 351
1

Here is how you can do this better with async and await:

    private async void WhatEverMethod()
    {
        var stream = await response.Content.ReadAsStreamAsync();

        using (FileStream fileStream = File.Create(fullFileName, (int)stream.Length))
        {
            byte[] bytesInStream = new byte[stream.Length];
            stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
            fileStream.Write(bytesInStream, 0, bytesInStream.Length);
        }
    });
Jordan
  • 9,642
  • 10
  • 71
  • 141