我试图同步使用HttpClient,但是当我发出许多并发请求时,它就停止工作了。我编写了两个测试,一个用于异步使用,另一个用于同步使用。TestMethod总是在4秒后返回响应。异步测试工作正常。几乎所有的请求都在同步测试中超时,只有~20个最后的请求是成功的。我尝试对请求使用单个HttpClient,并为每个新请求创建新的HttpClient实例。没什么区别。也许这和这个死锁有关。
我使用VS2013和.NET框架4.5.1针对Framework4.5。我通过HttpClient获得NuGet:<package id="Microsoft.Net.Http" version="2.2.15" targetFramework="net45" />
我还不想异步使用HttpClient,因为这意味着我必须重写我的整个应用程序。你知道我在这里做错了什么吗?
// all 800 requests complete successfully
[Test]
public async void Asyncmethod()
{
var sw = new Stopwatch();
sw.Start();
var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(15);
var tasks = Enumerable.Range(0, 800).Select(x => Task.Run(async () =>
{
try
{
var swx = new Stopwatch();
swx.Start();
var response = await client.GetStringAsync("http://localhost:7002/TestMethod").ConfigureAwait(false);
swx.Stop();
Console.WriteLine(x + " " + response + " in " + swx.ElapsedMilliseconds + " ms.");
}
catch (Exception e)
{
Console.WriteLine(x + " Exception: " + e.Message);
}
})).ToArray();
await Task.WhenAll(tasks);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
// almost all of 800 requests time out
[Test]
public void Syncmethod()
{
var sw = new Stopwatch();
sw.Start();
var client = new HttpClient();
var tasks = Enumerable.Range(0, 800).Select(x => Task.Run(() =>
{
try
{
var swx = new Stopwatch();
swx.Start();
var response = client.GetStringAsync("http://localhost:7002/TestMethod");
if (response.Wait(15000))
{
swx.Stop();
Console.WriteLine(x + " " + response.Result + " in " + swx.ElapsedMilliseconds + " ms.");
}
else
{
swx.Stop();
Console.WriteLine(x + " timed out.");
}
}
catch (Exception e)
{
Console.WriteLine(x + " Exception: " + e.Message);
}
})).ToArray();
foreach (var task in tasks)
task.Wait(60000);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}发布于 2013-10-22 12:53:49
我建议您将await用于HttpClient而不是Wait。如果您真的想要同步请求,请考虑使用支持同步方法的WebClient。
尽管如此,我相信您看到这种行为的原因是ServicePointManager.DefaultConnectionLimit,它将限制对给定服务器的请求数量。如果希望对同一服务器(同步或异步)具有大量并发请求,则需要增加该限制(对于UI应用程序,默认为2)。
发布于 2013-10-22 08:46:14
是的,这看起来像是僵局。
这个代码工作得很好。
public static void Syncmethod()
{
var sw = new Stopwatch();
sw.Start();
var client = new HttpClient();
var tasks = Enumerable.Range(0, 800).Select(x => Task.Run(() =>
{
var swx = new Stopwatch();
swx.Start();
var result =
client.GetStringAsync("http://yandex.ru").ContinueWith(task =>
{
try
{
swx.Stop();
Console.WriteLine(x + " " + task.Result + " in " + swx.ElapsedMilliseconds + " ms.");
return task.Result;
}
catch (Exception e)
{
swx.Stop();
Console.WriteLine(x + " Exception: " + e.Message);
throw e;
}
}, TaskContinuationOptions.AttachedToParent);
})).ToArray();
foreach (var task in tasks)
task.Wait(60000);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}我想你需要额外的逻辑来处理超时。例如,可能是在15秒内完成的另一项任务。
看看这篇文章HttpClient.GetAsync(.)使用“等待/异步”时永不返回
正如上面所描述的,您可以通过简单的更改挂起异步示例。
var response = client.GetStringAsync("http://yandex.ru").GetAwaiter().GetResult();当您编写异步代码时,永远不要使用块执行并等待结果.
https://stackoverflow.com/questions/19509283
复制相似问题