c# - Task.Factory.FromAsync 相当于 HttpWebRequest 和请求流代码

标签 c# .net asynchronous task-parallel-library task

我有以下扩展方法,用于在 WebRequest 对象上使用异步调用。

 public static Task<WebResponse> GetReponseAsync(this WebRequest request)
    {
        return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
    }

    public static Task<Stream> GetRequestStreamAsync(this WebRequest request)
    {
        return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null);
    }

我想使用这些扩展方法将以下代码转换为异步等效代码。

using (Stream rs = request.GetRequestStream())
{
   var postData = Encoding.ASCII.GetBytes(PostData);
   rs.Write(postData, 0, postData.Length);

   using (WebResponse response = request.GetResponse())
   using (StreamReader reader = new StreamReader(response.GetResponseStream()))
   {
       str = reader.ReadToEnd();

       rs.Close();
       reader.Close();
       response.Close();
   }
}

我使用另一段利用 WebRequest 的代码轻松完成了此操作,但这不需要第一次调用 GetRequestStream()。

request.GetReponseAsync().ContinueWith(t =>
{
    if (t.Exception == null)
    {
        using (var sr = new StreamReader(t.Result.GetResponseStream()))
        {
            str = sr.ReadToEnd();
        }
    }
});

如何转换第一个代码块以使用我的扩展方法并等效?

编辑我正在使用 .NET 4.0,因此目前无法选择 async/await。

最佳答案

您只需链接 ContinueWith来电。根据经验,序列中的每个异步操作都会有一个ContinueWith。每个ContinueWith 通常都会以 return <some async call> 结尾下一个将开始处理其结果。

request.GetRequestStreamAsync()
       .ContinueWith((trs) =>
           {
               var postData = System.Text.Encoding.ASCII.GetBytes("dummy");
               trs.Result.Write(postData, 0, postData.Length);
               return request.GetResponseAsync();
           }).Unwrap()
       .ContinueWith((resp) =>
           {
               using (var sr = new StreamReader(resp.Result.GetResponseStream()))
               {
                   var str = sr.ReadToEnd();
               }
           });

请注意,在我的代码(以及您的异步版本)中,并非所有对象都像原始对象一样被处置。

在每个步骤中,您可能需要检查 Status 或 IsFaulted/IsCanceled 属性,或者使用采用 TaskContinuationOptions 参数的ContinueWith 重载。对于后一个选项,请注意,前一个任务未以与选项匹配的方式完成会导致任务取消。如果您需要传递错误,则该方法不会。就我个人而言,我将所有检查包装到一个方法中,该方法要么传递错误并取消,要么在成功完成时运行委托(delegate)。否则,您很快就会得到大量样板检查代码。

关于c# - Task.Factory.FromAsync 相当于 HttpWebRequest 和请求流代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17664191/

相关文章:

c# - 我如何能够更改类外的私有(private)只读数组内的值?

c# - 如何使用 JSON.net 格式化嵌套 JSON 对象的输出?

c# - C#中的异步问题

python - 使用 Python 并行获取图像并异步保存它们

c# - 在 Azure 搜索 .NET SDK 中按复杂类型排序?

c# - 从 ListBox 中删除项目时,每个循环都不起作用

c# - 如何从 WebClient Response 解析编码?

c# - 如何将小数四舍五入?

android - 在 ViewPager 中使用 RecyclerView 的异步 Firebase 任务

c# - 创建一个列表,其中元素计数与另一个列表相关