多次调用 GetAsync 只执行一次
calling GetAsync multiple times only executes one time
我正在尝试在非阻塞异步函数中多次调用 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
异常(被默默忽略)
This instance has already started one or more requests. Properties can only be modified before sending the first request.
因此,第二个和第三个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,则必须将 Main 函数签名从 static void 更改为 static async Task。
我正在尝试在非阻塞异步函数中多次调用 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
异常(被默默忽略)
This instance has already started one or more requests. Properties can only be modified before sending the first request.
因此,第二个和第三个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,则必须将 Main 函数签名从 static void 更改为 static async Task。