我正在开发一个 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 }
答案 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
),直到您准备好使数据库方法异步。