Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create an async method in C# 4 according to the best practices?

Consider the following code snippet:

public static Task<string> FetchAsync()
{
    string url = "http://www.example.com", message = "Hello World!";

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Http.Post;

    return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)
        .ContinueWith(t =>
        {
            var stream = t.Result;
            var data = Encoding.ASCII.GetBytes(message);
            Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length, null, TaskCreationOptions.AttachedToParent)
                .ContinueWith(t2 => { stream.Close(); });
        })
        .ContinueWith<string>(t =>
        {
            var t1 =
                Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
                .ContinueWith<string>(t2 =>
                {
                    var response = (HttpWebResponse)t2.Result;
                    var stream = response.GetResponseStream();
                    var buffer = new byte[response.ContentLength > 0 ? response.ContentLength : 0x100000];
                    var t3 = Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null, TaskCreationOptions.AttachedToParent)
                        .ContinueWith<string>(t4 =>
                        {
                            stream.Close();
                            response.Close();
                            if (t4.Result < buffer.Length)
                            {
                                Array.Resize(ref buffer, t4.Result);
                            }
                            return Encoding.ASCII.GetString(buffer);
                        });
                    t3.Wait();
                    return t3.Result;
                });
            t1.Wait();
            return t1.Result;
        });
}

It should return Task<string>, send HTTP POST request with some data, return a result from webserver in a form of string and be as much efficient as possible.

  • Did you spot any problems regarding async flow in the example above?
  • Is it OK to have .Wait() inside .ContinueWith() in this example
  • Do you see any other problems with this peace of code (keeping aside exception handling for now)?
like image 682
Grief Coder Avatar asked Nov 16 '10 03:11

Grief Coder


People also ask

What does making a method async do?

The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.

What are async methods?

An async method runs synchronously until it reaches its first await expression, at which point the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method, as the example in the next section shows.

Does C have async await?

In C. There's no official support for await/async in the C language yet. Some coroutine libraries such as s_task simulate the keywords await/async with macros.


1 Answers

If async related C# 4.0 code is huge and ugly - there is a chance that it's implemented properly. If it's nice and short, then most likely it's not ;)

..though, you may get it look more attractive by creating extension methods on WebRequest, Stream classes and cleanup the main method.

P.S.: I hope C# 5.0 with it's new async keyword and library will be released soon.

Reference: http://msdn.microsoft.com/en-us/vstudio/async.aspx

like image 61
Konstantin Tarkus Avatar answered Sep 19 '22 11:09

Konstantin Tarkus