与线程相比,我不太了解 async/await 的好处。
在方法内部的情况下,我有一个没有异步/等待版本的操作在其他异步操作中间消耗一些时间,例如 20 毫秒。
调用此方法1000次,由于async/await只在一个线程内执行,在我的测试中至少会消耗20ms x 1000次(使用Thread.Sleep模拟)。
对async/await有什么误解吗?
public void Start()
{
Task[] task = new Task[500];
for (int i = 0; i < 500; i++)
{
task[i] = AsyncGet();
}
await Task.WhenAll(task);
}
public async Task<bool> AsyncGet()
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.example.com");
req.Method = "GET";
using(HttpWebResponse res = (HttpWebResponse)await req.GetResponseAsync())
{
Thread.Sleep(20);//Simulate an operation without async/await version that consume a little bit time
using (Stream responseStream = res.GetResponseStream())
{
StreamReader sr = new StreamReader(responseStream, Encoding.ASCII);
string resp = await sr.ReadToEndAsync();
}
}
}
更新问题:
如果我需要执行一些非异步/等待操作,例如在使用外部库获取 http 响应后操作 json。避免浪费时间的最佳做法是什么?
最佳答案
不,不一定。如果您从单线程的 SynchronizationContext 调用 Start
方法(比如任何 UI 上下文,如 WindowsFormsSynchronizationContext 或 DispatcherSynchronizationContext),答案是肯定的 [*]。
如果您从其他线程(比如工作线程)调用Start
。它不会占用 20 毫秒 x 1000。因为await之后的代码会在ThreadPool thread中执行在这种情况下。所以可以有 N 个线程在 await 之后执行代码。在您的情况下,N 将小于或等于 500。
就是说,您不应该在异步方法中阻塞。如果您需要在异步方法中使用任何同步代码,您应该使用 await Task.Run(()=> CodeThatBlocks())
* 如果 SynchronizationContext 没有被 SynchronizationContext.SetSynchronizationContext
覆盖
关于c# - async/await 方法中的耗时任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25699216/