C# 执行多个数据库调用-单线程还是多线程?

C# 执行多个数据库调用-单线程还是多线程?,c#,wpf,mvvm,async-await,C#,Wpf,Mvvm,Async Await,我试图了解在执行多个数据库调用时最好采用哪种方法。我有很多屏幕包含相同的模式: 在屏幕加载时异步(异步/等待)获取数据 将控件返回到UI线程,以便可以加载屏幕 在数据到达时的某个时刻更新UI 有些屏幕只有一个数据库调用,有些屏幕有多个数据库调用 典型的数据库调用 private Task<List<Product>> GetProductsAsync() { TaskCompletionSource<List<Product>

我试图了解在执行多个数据库调用时最好采用哪种方法。我有很多屏幕包含相同的模式:

  • 在屏幕加载时异步(异步/等待)获取数据
  • 将控件返回到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();
    CustomerList = await GetCustomersAsync();
    OtherList = await GetOthersAsync();
}
如您所见,当前实现将通过多个调用从屏幕上的线程池中生成多个线程。这是正确的方法吗

另一种方法是在一个任务中检索所有数据,但这将导致在tcs.result中检索一个列表数组,这有点不清楚(从代码可读性的角度)检索的是什么


您认为在自己的线程中执行每个数据库调用是正确的方法吗?如果不是,您的建议是什么?

当您使用
async wait
时,所有调用都可以在不同的线程上运行,但不一定同时(并发)运行。在您的情况下,所有调用都是连续的,因此您不会同时命中数据库

关于对数据库进行并发调用,这取决于数据库本身。大多数数据库可以同时处理多个调用,特别是在不同的表上。但是,如果并发操作使用相同的锁,则可能会增加争用。这两种方法都可以,但在大多数情况下,并发调用数据库是一件好事


关于
GetProductsAsync
为什么要使用TaskCompletionSource而不是:

private Task<List<Product>> GetProductsAsync()
{
    return Task.Run(() => Repository.GetAllProducts());
}
私有任务GetProductsAsync()
{
返回Task.Run(()=>Repository.GetAllProducts());
}

您当前的实现不会产生多个线程。在调用下一个方法之前,它在您等待时一个接一个地执行。@Sriram Sakthivel对products的第一次调用将产生一个新线程,因为TaskEx.Run将从线程池中获取一个新线程。第二次调用、第三次调用等也是如此。对产品的第一次调用将产生一个新线程,但
wait
将异步等待,直到
GetProductsAsync
完成。只有这样,它才会调用
getCustomerAsync
。所以这里不需要多个线程。完成
GetProductsAsync
任务的同一线程可以执行
getCustomerAsync
任务等等。你明白我的意思了吗?如果您需要同时完成这三项任务,则需要同时启动它们并与
wait Task一起等待它们。何时
您确定您的数据库可以同时处理查询?如果没有这些,多线程将毫无意义。@Goran这就是我想说的。我没有说它将在单线程中执行。再读一遍我的评论。我说同一个线程可以执行下一个任务。我的意思是,你是一个接一个地做这件事,而不是一次性完成。我已经不使用并发调用,所以我不明白你的建议?我使用的是EF DbContexr,它不支持concurent调用,但我没有指定我使用的ORM,因为它在本例中并不重要。我试图避免人们建议使用新的EF6异步功能,因为我使用的是4.0框架,所以我不能使用,EF6异步功能仅在4.5+上受支持。关于您添加的部分,是的,tsc在这里完全足够。我的qyestion是ore of,是否可以生成5个不同的线程来获取数据,还是应该将所有调用封装到一个线程中。或者整体性能没有受到影响,我应该选择第一个,这更容易理解。@Goran你问哪个是正确的。单线程或多线程数据库调用。两者都是正确的,但并发调用可能会获得更好的结果。这就是我的答案。@Goran您的代码不是多线程的,并且您没有生成5个不同的线程。没有理由使用TCS来创建任务,而不仅仅是使用您已有的任务。我的代码是多线程的,每次执行TaskEx.Run()时,我都会创建新线程。每次Run()时,我都会得到一个具有不同ManagedThreadId的新线程,这意味着每次发出不同的数据库调用时,它都会分配不同的线程。我已经对TCS发表了评论。。。
private Task<List<Product>> GetProductsAsync()
{
    return Task.Run(() => Repository.GetAllProducts());
}