使用AsyncCallbacks将方法转换为Task <result>方法</result>

时间:2014-06-12 16:30:20

标签: c# .net windows-phone-8

希望将我的方法从HttpWebRequest.BeginGetRequestStream和HttpWebRequest.BeginGetResponse更改为使用async和Tasks的方法。我需要使用这些方法,因为我在Windows Phone上工作,并且此平台上没有其他非异步的GetRequestStream方法。

这是我的方法DownloadString:

private static Action<string> completed;

    public static void DownloadString(Action<string> c)
    {
        completed = c;

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("linkhere", UriKind.Absolute));
        request.Method = "POST";
        request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5Accept: */*";
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.BeginGetRequestStream(RequestCallback, request);
    }

    private static void RequestCallback(IAsyncResult ar)
    {
        HttpWebRequest request = (HttpWebRequest)ar.AsyncState;

        Stream postStream = request.EndGetRequestStream(ar);
        //some post data

        request.BeginGetResponse(ResponseCallback, request);
    }

    private static void ResponseCallback(IAsyncResult ar)
    {
        HttpWebRequest webRequest = (HttpWebRequest)ar.AsyncState;
        HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(ar);

        Stream streamResponse = response.GetResponseStream();
        StreamReader streamReaders = new StreamReader(streamResponse);
        string content = streamReaders.ReadToEnd();
        streamResponse.Close();
        streamReaders.Close();
        response.Close();

        completed.Invoke(content);
    }

对于下一步,我使用了以下链接: Converting Callback Functions to Task Pattern 现在我想要一个这样的包装器方法:

 public async static Task<string> DownloadWithoutAction()
    {
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
        var task = tcs.Task;
        Action<string> callback = tcs.SetResult;
        await Task.Factory.StartNew(() =>
        {
            DownloadString(callback);
        }, TaskCreationOptions.AttachedToParent);
        return await Task.FromResult(task.Result);
    }

问题: 这不起作用,因为回调是异步的,因此线程在回调被触发之前停止。这只是我的猜测。我该如何解决?

提前致谢

2 个答案:

答案 0 :(得分:3)

首先,我强烈建议您升级到HttpClient

但如果你想以更难的方式去做,那么你会做这样的事情:

public static Task<string> DownloadStringAsync()
{
  TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
  DownloadString(result => tcs.SetResult(result));
  return tcs.Task;
}

答案 1 :(得分:0)

您可以使用TaskFactory中的FromAsync方法:

var request = HttpWebRequest.CreateHttp("http://url");
var stream = await Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, TaskCreationOptions.None);
var response = (HttpWebResponse)(await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, TaskCreationOptions.None));

使用Tasks的方法可以是:

private async Task<string> DownloadString()
{
    var request = (HttpWebRequest)WebRequest.Create(new Uri("linkhere", UriKind.Absolute));
    request.Method = "POST";
    request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5Accept: */*";
    request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";

    using (var response = (HttpWebResponse)(await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, TaskCreationOptions.None)))
    using (var streamResponse = new StreamReader(response.GetResponseStream()))
    {
        return await streamResponse.ReadToEndAsync();
    }
}