C# 中的异步 Main 和阻止异步 Http 调用
async Main in C# and blocking async Http calls
我对从我认为是纯异步程序中得到的输出感到很困惑。
如您所见,没有明显的反模式(我希望如此)和阻塞调用。
slowURL
限制服务器响应 10 秒。我确实通过 运行 以 10 秒超时调用本地服务器确认当 运行 控制台中的代码时 FetchSlowAsync
方法调用有效地阻塞主线程 10 秒。
我预计 TaskScheduler 不会按顺序安排调用,而是始终随机确定方法调用顺序。唉,输出总是确定的。
FetchSlowAsync start
FetchSlowAsync got data!
FetchAsync start
FetchAsync got data!
FetchBingAsync start
FetchBingAsync got data!
All done!
我的问题是:是什么提示 FetchSlowAsync
阻止而不是 TaskScheduler 执行上下文切换到另一个异步方法并在完成后返回它?
前者之后的下一个问题:为什么在异步执行模型是并发的情况下,async Main
中的所有方法的执行顺序与它们被调用的顺序相同?
using static System.Console;
using System.Net.Http;
using System.Threading.Tasks;
class Start
{
const string serviceURL = "https://google.com";
const string slowDown = "http://slowwly.robertomurray.co.uk/delay/10000/url/";
const string slowURL = slowDown + serviceURL;
const string OkURL = serviceURL;
static async Task FetchSlowAsync()
{
await Console.Out.WriteLineAsync("FetchSlowAsync start");
await new HttpClient().GetStringAsync(slowURL); //BLOCKS MAIN THREAD FOR 10 seconds
await Console.Out.WriteLineAsync("FetchSlowAsync got data!");
}
static async Task FetchAsync()
{
await Console.Out.WriteLineAsync("FetchAsync start");
await new HttpClient().GetStringAsync(OkURL);
await Console.Out.WriteLineAsync("FetchAsync got data!");
}
static async Task FetchBingAsync()
{
await Console.Out.WriteLineAsync("FetchBingAsync start");
await new HttpClient().GetStringAsync("https://bing.com");
await Console.Out.WriteLineAsync("FetchBingAsync got data!");
}
static async Task Main()
{
await FetchSlowAsync();
await FetchBingAsync();
await FetchAsync();
await System.Console.Out.WriteLineAsync("All done!");
}
}
目前,您正在等待从 FetchSlowAsync()
返回的任务完成,然后再继续调用 FetchBingAsync
等。您正在等待任务,在这里:
await FetchSlowAsync();
await FetchBingAsync();
await FetchAsync();
如果你不想等slow fetch完成再开始Bing fetch等,你可以记住他们返回的任务,稍后再等待:
static async Task Main()
{
// Start all three tasks
Task t1 = FetchSlowAsync();
Task t2 = FetchBingAsync();
Task t3 = FetchAsync();
// Then wait for them all to finish
await Task.WhenAll(t1, t2, t3);
await Console.Out.WriteLineAsync("All done!");
}
现在 你得到了我认为你期望的那种输出。例如,我的机器上有一个 运行:
FetchSlowAsync start
FetchBingAsync start
FetchAsync start
FetchAsync got data!
FetchBingAsync got data!
FetchSlowAsync got data!
All done!
我对从我认为是纯异步程序中得到的输出感到很困惑。 如您所见,没有明显的反模式(我希望如此)和阻塞调用。
slowURL
限制服务器响应 10 秒。我确实通过 运行 以 10 秒超时调用本地服务器确认当 运行 控制台中的代码时 FetchSlowAsync
方法调用有效地阻塞主线程 10 秒。
我预计 TaskScheduler 不会按顺序安排调用,而是始终随机确定方法调用顺序。唉,输出总是确定的。
FetchSlowAsync start
FetchSlowAsync got data!
FetchAsync start
FetchAsync got data!
FetchBingAsync start
FetchBingAsync got data!
All done!
我的问题是:是什么提示 FetchSlowAsync
阻止而不是 TaskScheduler 执行上下文切换到另一个异步方法并在完成后返回它?
前者之后的下一个问题:为什么在异步执行模型是并发的情况下,async Main
中的所有方法的执行顺序与它们被调用的顺序相同?
using static System.Console;
using System.Net.Http;
using System.Threading.Tasks;
class Start
{
const string serviceURL = "https://google.com";
const string slowDown = "http://slowwly.robertomurray.co.uk/delay/10000/url/";
const string slowURL = slowDown + serviceURL;
const string OkURL = serviceURL;
static async Task FetchSlowAsync()
{
await Console.Out.WriteLineAsync("FetchSlowAsync start");
await new HttpClient().GetStringAsync(slowURL); //BLOCKS MAIN THREAD FOR 10 seconds
await Console.Out.WriteLineAsync("FetchSlowAsync got data!");
}
static async Task FetchAsync()
{
await Console.Out.WriteLineAsync("FetchAsync start");
await new HttpClient().GetStringAsync(OkURL);
await Console.Out.WriteLineAsync("FetchAsync got data!");
}
static async Task FetchBingAsync()
{
await Console.Out.WriteLineAsync("FetchBingAsync start");
await new HttpClient().GetStringAsync("https://bing.com");
await Console.Out.WriteLineAsync("FetchBingAsync got data!");
}
static async Task Main()
{
await FetchSlowAsync();
await FetchBingAsync();
await FetchAsync();
await System.Console.Out.WriteLineAsync("All done!");
}
}
目前,您正在等待从 FetchSlowAsync()
返回的任务完成,然后再继续调用 FetchBingAsync
等。您正在等待任务,在这里:
await FetchSlowAsync();
await FetchBingAsync();
await FetchAsync();
如果你不想等slow fetch完成再开始Bing fetch等,你可以记住他们返回的任务,稍后再等待:
static async Task Main()
{
// Start all three tasks
Task t1 = FetchSlowAsync();
Task t2 = FetchBingAsync();
Task t3 = FetchAsync();
// Then wait for them all to finish
await Task.WhenAll(t1, t2, t3);
await Console.Out.WriteLineAsync("All done!");
}
现在 你得到了我认为你期望的那种输出。例如,我的机器上有一个 运行:
FetchSlowAsync start
FetchBingAsync start
FetchAsync start
FetchAsync got data!
FetchBingAsync got data!
FetchSlowAsync got data!
All done!