1

我是 .Net 和 Windows Phone 开发的新手。我目前正在研究通过 HTTPWebrequest 类发出异步 Web 请求的不同方法。

异步和等待:

async 和 await 似乎是一种发出异步 Web 请求的好方法:http: //blog.stephencleary.com/2012/02/async-and-await.html。我唯一担心的是,根据文档,在执行任务时调用方法线程会被挂起。我希望调用方法立即返回,我该怎么做?

public async Task NewStuffAsync()
{
  // Use await and have fun with the new stuff.
  await ...
}

public Task MyOldTaskParallelLibraryCode()
{
  // Note that this is not an async method, so we can't use await in here.
  ...
}

public async Task ComposeAsync()
{
  // We can await Tasks, regardless of where they come from.
  await NewStuffAsync();
  await MyOldTaskParallelLibraryCode();
}

HttpWebRequest.BeginGetResponse

这是来自 Microsoft 的示例:http: //msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx ?cs-save-lang=1&cs-lang=csharp#code-snippet-2

我想了解与回调相关的开销。

线程池

托管线程池似乎很健壮。我再次想了解与之相关的开销。

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

4

4 回答 4

3

我实际上一直在尝试这个。我发布了代码,以便您可以使用它。async使用/await和使用回调实际上是有区别的。async/await对我来说更自然。

考虑以下代码。顺便说一句,这是一个控制台应用程序。两种代码都实现了相同的目标。

    static void Main(string[] args)
    {
        MakeRequest();       

        Console.ReadLine();
    }

    private static async void MakeRequest()
    {
        await UseHttpClient();
        UseWebClient();
    }

    private static async Task UseHttpClient()
    {
        Console.WriteLine("=== HttpClient ==");
        var client = new HttpClient();
        var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
        Console.WriteLine("HttpClient requesting...");
        var response = await client.SendAsync(request);
        Console.WriteLine(response.Content.ReadAsStringAsync().Result.Substring(0,100));
        Console.WriteLine("HttpClient done");
    }

    private static void UseWebClient()
    {
        Console.WriteLine("=== WebClient ==");
        var webClient = new WebClient();
        webClient.DownloadStringAsync(new Uri("http://www.google.com"));
        Console.WriteLine("WebClient requesting...");
        webClient.DownloadStringCompleted += (sender, eventArgs) => Console.WriteLine(eventArgs.Result.Substring(0,100));
        Console.WriteLine("WebClient done.");
    }

这些是输出:

为了HttpClient

=== HttpClient ==
HttpClient requesting...
<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">
<head><meta itemprop
HttpClient done

使用WebClient回调

=== WebClient ==
WebClient requesting...
WebClient done.
<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">
<head><meta itemprop

如您所见,HttpClient在继续流程之前实际上首先等待结果(它实际上返回给调用者)。因此,关键字await, 它等待并稍后执行。

但是使用回调时流程完全不同。您的代码流连续不断(这就是为什么您可以看到WebClient done在实际结果之前打印的原因。为了实现与 async/await 相同的流程,有多种方法。其中一种是利用 TCS 并将您的函数包装在它周围(我不会在这里介绍,因为这已经介绍过很多次了)。最简单的方法是使用HttpClient.

希望它有助于理解async/await和使用回调。

于 2013-05-25T15:55:36.500 回答
0

我建议安装Microsoft.Net.Http NuGet 包并使用 HttpClient。这内置了异步等待支持。

于 2013-05-24T04:35:00.323 回答
0

我唯一担心的是,根据文档,在执行任务时调用方法线程会被挂起。

不; 使用async/ await,你可以这样想:方法被挂起,但线程返回并继续运行。所以 UI 仍然是响应式的。

正如 Blounty 建议的那样,HttpClientMicrosoft.Net.Http包中签出(目前在 RC 中)。

于 2013-05-24T04:51:07.480 回答
0

我有同样的问题,我发现了这个并帮助了我

private async Task<T> ExecuteAsync<T>(RestRequest request)
{
    var tcs = new TaskCompletionSource<T>();
    _client.ExecuteAsync(request, resp =>
    {
        var value = JsonConvert.DeserializeObject<T>(resp.Content);
        if (value.ErrorCode > 0)
        {
            var ex = new ToodledoException(value.ErrorCode, value.ErrorDesc);
            tcs.SetException(ex);
        }
        else
            tcs.SetResult(value);
    });
    return await tcs.Task;
}

http://www.developer.nokia.com/Community/Wiki/Asynchronous_Programming_For_Windows_Phone_8我也发现这个扩展很有帮助http://nuget.org/packages/WP8AsyncWebClient/

于 2013-06-18T09:26:09.280 回答