TL; DR:
是否可以使用async await
?
不太简短:
试着学习async await
。在this video(“C#和Visual Basic的异步最佳实践”)中,演讲者举例说明如何使用async await
启动一些IO绑定工作。他明确地说(在21分40秒)同时解释了为什么并行for循环不是最佳的,因为它们消耗了大量的线程:
我们不需要更多线程。我们不需要两个线程......
我们是否真的可以在不使用多个线程的情况下异步启动多个请求?怎么样?不幸的是,发言人没有提供所有的代码,所以这是我的抨击:
// Pretty much exactly the same as video
private async Task<List<string>> LoadHousesAsync()
{
// Running on the UI thread
Debug.Print("Thread: " + Thread.CurrentThread.ManagedThreadId);
var tasks = new List<Task<string>>();
for (int i = 0; i < 5; i++)
{
Task<string> t = LoadHouseAsync(i);
tasks.Add(t);
}
string[] loadedHouses = await Task.WhenAll(tasks);
return loadedHouses.ToList();
}
// My guess of the LoadHouseAsync method
private Task<string> LoadHouseAsync(int i)
{
// Running on the UI thread
Debug.Print("Thread: " + Thread.CurrentThread.ManagedThreadId);
return Task.Run(() => LoadHouse(i));
}
// My guess of the LoadHouse method
private string LoadHouse(int i)
{
// **** This is on a different thread :( ****
Debug.Print("Thread: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5000); // simulate I/O bound work
return "House" + i;
}
这是输出。
Thread: 10
Thread: 10
Thread: 3
Thread: 10
Thread: 10
Thread: 11
Thread: 10
Thread: 12
Thread: 10
Thread: 13
Thread: 14
答案 0 :(得分:6)
您可以使用异步I / O执行此操作。你做的是做错的一个很好的例子(不幸的是,它也很常见)。
Task.Run
在线程池线程上运行方法,Thread.Sleep
阻塞线程。因此,您的示例模拟在多个线程上执行同步(阻塞)I / O.
要正确执行异步I / O,您需要始终使用异步方法。切勿将Task.Run
用于I / O.您可以使用Task.Delay
模拟异步I / O方法:
private async Task<string> LoadHouseAsync(int i)
{
Debug.Print("Thread: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(5000); // simulate async I/O bound work
return "House" + i;
}
答案 1 :(得分:0)
我们是否可以在不使用多个线程的情况下真正启动多个请求?
是的,这是一个真实世界的例子(伪asp.net-mvc和实体框架,例如,EF将对Sql Server进行IO调用)。
public async ActionResult()
{
var model = new Company();
using (var db1 = new DbContext)
using (var db2 = new DbContext)
{
var task1 = db1.Employees.ToListAsync();
var task2 = db1.Managers.ToListAsync();
await Task.WhenAll(task1, task2);
model.employees = task1.Result;
model.managers = task2.Result;
}
return View(model);
}