如何根据最佳实践在C#4中创建异步方法?

时间:2010-11-16 03:14:16

标签: c# parallel-processing task

请考虑以下代码段:

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;
        });
}

它应返回Task<string>,发送带有一些数据的HTTP POST请求,以字符串形式从webserver返回结果,并尽可能高效。

  • 您是否发现上述示例中有关异步流量的任何问题?
  • 在此示例中是否可以使用.Wait().ContinueWith()
  • 您是否看到此代码安静存在任何其他问题(暂时搁置异常处理)?

2 个答案:

答案 0 :(得分:3)

如果异步相关的C#4.0代码庞大且丑陋 - 它有可能正确实现。如果它很好而且很短,那么很可能它不是;)

但是,你可以通过在WebRequest,Stream类上创建扩展方法并清理主要方法来使它看起来更具吸引力。

P.S。:我希望C#5.0及其新的async关键字和library即将发布。

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

答案 1 :(得分:0)

你认为Waits是不必要的是正确的 - 结果将阻塞,直到结果准备好。


但是,更简单的方法是使用ParallelExtensionsExtras library中提供的示例。

他们为WebClient添加了完全您正在寻找的内容:

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

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

您可以在this post on the Parallel Programming with .NET blog中了解更多相关信息。