【发布时间】:2014-10-12 04:49:58
【问题描述】:
我试图了解在执行多个数据库调用时最好采用哪种方法。我有很多包含相同模式的屏幕:
- 在屏幕加载时异步获取数据(async/await)
- 将控制权返回给 UI 线程,以便可以加载屏幕
- 在数据到达时更新 UI
有些界面只有一个数据库调用,有些界面有多个数据库调用。
一个典型的数据库调用
private Task<List<Product>> GetProductsAsync()
{
TaskCompletionSource<List<Product>> tcs = new TaskCompletionSource<List<Product>>();
TaskEx.Run(() => tcs.SetResult(Repository.GetAllProducts()));
return tcs.Task;
}
单次通话在屏幕上的使用
// an event handler,can be marked as async void
public override async void OnActivated()
{
base.OnActivated();
ProductList = await GetProductsAsync();
}
在屏幕上多次调用
// an event handler,can be marked as async void
public override async void OnActivated()
{
base.OnActivated();
ProductList = await GetProductsAsync();
CustomerList = await GetCustomersAsync();
OtherList = await GetOthersAsync();
}
如您所见,当前实现将从屏幕上的线程池中生成多个线程,并进行多次调用。这是正确的做法吗?
另一种方法是在一个任务中检索所有数据,但这会导致在 tcs.Result 中检索列表数组,这有点不清楚正在检索什么(从代码可读性的角度来看)。
您认为在自己的线程中执行每个数据库调用是正确的方法吗?如果不是,您的建议是什么?
【问题讨论】:
-
您当前的实现不会产生多个线程。在调用下一个方法之前,它会在您等待时一一执行。
-
@Sriram Sakthivel 第一次调用 products 将产生一个新线程,因为 TaskEx.Run 将从线程池中获取一个新线程。第二次呼叫、第三次呼叫等也是如此……
-
对产品的第一次调用将产生一个新线程,但
await将异步等待GetProductsAsync完成。只有这样它才会调用GetCustomersAsync。所以这里不需要多线程。完成GetProductsAsync任务的同一线程可以执行GetCustomersAsync任务等等。你明白我的意思了吗?如果您需要同时完成这三个操作,您需要同时启动它们并与await Task.WhenAll一起等待它们 -
您确定您的数据库可以处理同时查询吗?没有它,多线程将毫无意义。
-
@Goran 这就是我想说的。我没有说它将在单线程中执行。再次阅读我的评论。我说同一个线程可以执行下一个任务。我的意思是你是一件一件地做,而不是一口气做完。
标签: c# wpf mvvm async-await