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

发布于 2024-10-02 19:39:18 字数 2244 浏览 4 评论 0 原文

考虑以下代码片段:

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,发送带有一些数据的 HTTP POST 请求,以字符串形式从 Web 服务器返回结果,并尽可能高效。

  • 您在上面的示例中发现了有关异步流的任何问题吗?
  • 在此示例中,可以在 .ContinueWith() 中包含 .Wait() 吗?
  • 您是否发现这种和平的代码存在任何其他问题(暂时保留异常处理)?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

圈圈圆圆圈圈 2024-10-09 19:39:18

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

..不过,您可以通过在 WebRequest、Stream 类上创建扩展方法并清理主方法来使其看起来更有吸引力。

PS:我希望 C# 5.0 具有新的 async 关键字和 即将发布。

参考http://msdn.microsoft.com/ zh-cn/vstudio/async.aspx

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

和影子一齐双人舞 2024-10-09 19:39:18

您认为等待是不必要的,这是正确的 - 结果将阻塞,直到结果准备好。


但是,更简单的方法是使用 ParallelExtensionsExtras 中提供的示例进行基础库

他们为 WebClient 制作了扩展,它完全可以满足您的需求:

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

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

您可以在 这篇关于 .NET 并行编程博客的文章< /a>.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文