使用Task.Run方法异步等待数据库调用

时间:2019-11-21 16:50:48

标签: c# asynchronous async-await task

我们有一个异步/等待方法GetLoanDataAsync,该方法通过实体框架调用存储的过程,而该实体框架由同步方法GetData调用。

GetLoanData需要花费大量的时间来执行,这可能就是我们编写为异步/等待并可以在多个地方使用的原因的原因。

我知道我们不应该混用异步和同步调用,但是如果我们遇到这种情况,我们正在使用Task.Run()从同步方法GetLoanDataAsync调用异步方法GetData我了解该方法-GetLoanDataAsync将在后台线程上运行。

我的问题是,如果我们有一个异步版本GetLoanDataAsync的同步版本并使用Task.Run()中的GetData进行调用,那将有什么不同呢?

提供有关该问题的更多详细信息-

我们有ASP.NET REST Web API,其返回类型不是Task。这是从角度应用程序调用的。这个api有几个叫GetData()的方法,我们在这里等待GetLoanDataAsync的结果。据我了解,GetLoanDataAsync将在后台线程中被调用并能够执行GetUserDetails(),一旦完成,它将退回已执行的GetLoanDataAsync的结果。

代码-

public List<int> GetData(int id)
{

    // Calls GetLoanDataAsync

    var result = Task.Run(()=> GetLoanDataAsync(id));

    // calls couple other sync methods

    GetUserDetails(); 

    return result.GetAwaiter().GetResult();

}

GetLoanDataAsync().Result将导致死锁,这是较早的问题。为了解决这个问题,我们暂时尝试使用Task.Run,​​直到将整个api设为异步。

1 个答案:

答案 0 :(得分:4)

如果比较同步版本与异步版本,则最明显的区别是,同步版本在DB调用期间占用了线程,如果所有工作都在数据库中进行,则这似乎是不必要的。这是否是一个问题,取决于您的吞吐量。

通过使用Task.Run,您可以将该操作与其他工作并行进行。只要您没有影响线程安全性的接触点或依赖于单个逻辑执行流的接触点,就可以了。

如果您想有效地使用异步,最好将其视为“粘性”-即,如果X是异步的,则调用X(直接或间接)的所有内容都必须是异步的。