Task.Factory.FromAsync等效于HttpWebRequest和请求流代码

时间:2013-07-15 21:22:35

标签: 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目前不是一个选项。

1 个答案:

答案 0 :(得分:3)

您只需要链接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重载。对于后一种选择,请注意先前的任务未以匹配选项的方式完成会导致取消任务。如果您需要传递错误,那么这种方法就不会。就个人而言,我将所有检查包装到一个方法中,该方法要么通过错误要么取消,要么在成功完成时运行委托。否则,您很快就会得到很多样板检查代码。