从asp.net web api中的异步方法调用同步方法

时间:2021-06-25 11:40:00

标签: c# async-await

我正在开发一个 C# asp.net Web API 项目。我是异步编程的新手。

在我的 GetOrderNumberAsync 异步方法中,我必须调用旧同步方法,如第 20 行所示。这是更新 SQL 服务器表中数据的数据库调用。

我正在考虑使用 Task.Run() 重写它,如第 21 行所示。

会导致死锁吗?经过广泛的 Google 搜索后,我找不到明确的答案。

1 [HttpPost]
2 [Route("FreshOrder")]
3 public async Task FreshOrder([FromBody] JObject jsonResult)
4 {
5    string resourceURL = JObject.Parse(jsonResult.ToString())["resource_url"].ToString();
6    await GetOrderNumberAsync(resourceURL);
7 }

8 private async Task GetOrderNumberAsync(string queryURL)
9 {
10  int rowsAffected;
11    using (HttpClient client = new HttpClient())
12    {

13  string resp = await client.GetStringAsync(queryURL);

14  var jObj = JObject.Parse(resp);
15  JArray orders = (JArray)jObj["orders"];

16  foreach (JToken order in orders)
17  {
18         string customerId = (string)order["customerId"];
19     string customerNumber = (string)order["customerNumber"];
20     rowsAffected = order.UpdateData(customerId, customerNumber);
21     //rowsAffected = await Task.Run(() => 
       //  order.UpdateData(customerId, 
       //customerNumber));
22  }       
23 }

1 个答案:

答案 0 :(得分:3)

您不应该使用 Task.Run,但不是因为您认为的原因。

Task.Run 不会导致死锁。 common deadlock 当某些代码在单线程上下文中阻塞异步代码时发生。在这种情况下,代码在后台线程 (Task.Run) 上运行同步代码,然后 await 运行它。这不会死锁。

但是,您仍然不应该使用 Task.Run。这是因为 ASP.NET 已经在线程池线程上运行此请求。 await Task.Run 会将部分请求(数据库更新)调度到不同 线程池线程上,然后“让步”回 ASP.NET 运行时,将当前线程池线程返回到线程池。因此,在 ASP.NET 上,Task.Run 只会导致线程切换而没有任何好处。 Quote

<块引用>

您可以通过等待 Task.Run 来启动一些后台工作,但这样做毫无意义。事实上,这实际上会干扰 ASP.NET 线程池启发式算法,从而损害您的可伸缩性……作为一般规则,不要将工作排队到 ASP.NET 上的线程池。

如果该方法已经是异步的(或者如果该方法有异步版本),那么您的代码当然应该将它与 await 一起使用。但由于代码是同步的,只需将其设为直接同步调用(无 Task.Run),直到您准备好使数据库方法异步。