代码之家  ›  专栏  ›  技术社区  ›  Grief Coder

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

  •  14
  • Grief Coder  · 技术社区  · 14 年前

    请考虑以下代码段:

    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请求,以字符串的形式从web服务器返回结果,并尽可能高效。

    • 你在上面的例子中发现了关于异步流的任何问题吗?
    • 在本例中,可以在.ContinueWith()中使用.Wait()吗
    • 您是否看到这种代码平和(暂时不处理异常)的其他问题?
    2 回复  |  直到 13 年前
        1
  •  3
  •   Konstantin Tarkus    14 年前

    如果异步相关的C#4.0代码是 又大又丑 -它有可能被正确地执行。如果它又短又好,那么很可能不是;)

    …不过,通过在WebRequest、Stream类上创建扩展方法并清理main方法,您可能会使它看起来更有吸引力。

    附笔。 :我希望新的C#5.0 async 关键字和 library 很快就会被释放。

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

        2
  •  0
  •   porges    14 年前

    您认为等待是不必要的,这是正确的—结果将阻塞,直到结果就绪。


    然而,更简单的方法是使用 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 .

    推荐文章