How to create an async method in C# 4 according to

2019-02-02 10:42发布

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)?

2条回答
家丑人穷心不美
2楼-- · 2019-02-02 11:09

You're correct in thinking that the Waits are unnecessary - Result will block until a result is ready.


However, an even easier way would be to base it off use the examples provided in the ParallelExtensionsExtras library.

They have made extensions for WebClient which do exactly what you're looking for:

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

    return new WebClient().UploadStringTask(url, "POST", message);
}

You can read more about it in this post on the Parallel Programming with .NET blog.

查看更多
放我归山
3楼-- · 2019-02-02 11:35

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

查看更多
登录 后发表回答