我试图在非阻塞异步函数中多次调用 GetAsync 。令我惊讶的是,只有第一个调用被执行。所有请求都发送到同一个域,因此我认为重用
HttpClient
是有意义的。为什么只执行第一个请求,我应该如何重写代码?
private static HttpClient client = new HttpClient(new HttpClientHandler(){UseProxy = false});
private static async Task NonblockingGet(string destination){
client.Timeout = TimeSpan.FromSeconds(10);
var result = await client.GetAsync(destination);
// handle result
}
private static void CallMultipleTimes(){
NonblockingGet("domain1/url1"); // only this one is executed
NonblockingGet("domain1/url2");
NonblockingGet("domain1/url3");
}
//main
ManualResetEvent mre = new ManualResetEvent(false);
CallMultipleTimes();
mre.WaitOne();
否,对
NonblockingGet
的所有三个调用均已执行。但在第二次调用时,您尝试在已经启动请求后修改client
(即设置超时)。这是不允许的,它会抛出一个 System.InvalidOperationException
异常(被默默忽略)
该实例已启动一个或多个请求。属性只能在发送第一个请求之前修改。
因此,当然,第二个和第三个
client.GetAsync()
不会被执行。
将
client.Timeout = TimeSpan.FromSeconds(10);
移至 CallMultipleTimes()
中的第一个语句(或在第一个请求之前仅执行一次的其他位置),一切都会按预期工作(至少对于此用例)。
private static async Task NonblockingGet(string destination){
// client.Timeout = TimeSpan.FromSeconds(10); // <--- remove it here
var result = await client.GetAsync(destination);
// handle result
}
private static void CallMultipleTimes(){
client.Timeout = TimeSpan.FromSeconds(10); // <--- add it here
NonblockingGet("domain1/url1"); // only this one is executed
NonblockingGet("domain1/url2");
NonblockingGet("domain1/url3");
}
我不明白为什么只执行第一个调用(我自己尝试了代码,所有代码都被正确调用)。然而,通常您不想将线程等待与异步代码混合在一起。并且您希望所有异步操作在任务中等待并执行(为了正确的异常处理)。
这是我的建议
HttpClient client = new HttpClient(new HttpClientHandler() { UseProxy = false});
async Task NonblockingGet(string destination)
{
client.Timeout = TimeSpan.FromSeconds(10);
var result = await client.GetAsync(destination);
// handle result
}
async Task CallMultipleTimes() =>
await Task.WhenAll(NonblockingGet("domain1/url1"), NonblockingGet("domain1/url2"), NonblockingGet("domain1/url3"));
// Main
await CallMultipleTimes();
// If you are here all 3 operations requests are completed
注意:如果您使用.Net < 6.0 you have to change your Main function signature from static void to static async Task.
我遇到了类似的问题,尽管我无法找出确切的根本原因,但我终于能够克服这个问题,其中只有对 api 的第一个调用成功执行,而所有其他调用都抛出
403 Forbidden
实施以下
解决方案并从使用切换后,出现错误:
private static readonly HttpClient client = new HttpClient();
使用方法:
IHttpClientFactory factory = new ServiceCollection()
.AddHttpClient()
.BuildServiceProvider()
.GetRequiredService<IHttpClientFactory>();