在 Task.Run 中调用异步方法

call method async inside Task.Run

下面显示的代码在 asp.net mvc 应用程序中执行

public async Task<string> GetCustomers1(){
    return await getcustomer1Async();
}
public async Task<string> GetCustomers2(){
    return await getcustomer2Async();
}
public async Task<JsonResult> Index(){
   var result1 =Task.Run(()=>GetCustomers1());
   var result2 =Task.Run(()=>GetCustomers2());
   Task.WaitAll(result1,result2);

}

我很清楚任务 运行 将创建两个线程来执行方法 GetCustomers1、GetCustomers2。 - 我的问题是,当方法 GetCustomers1 和 GetCustomers2 到达带有 await 字样的行时,未完成的任务应该 returned,未完成的任务应该在哪里 returned?是否线程return到线程池? -Task.WaitAll 你会让主线程一直忙到其他任务完成 运行ning 吗?

我知道如果方法是异步的,你不应该使用 tak.run。但是我想知道在这种情况下代码在内部是如何工作的。

是的,在 await 行,方法 GetCustomers1GetCustomers2 将立即 return 一个未完成的任务,假设任务 return 来自getcustomer1Async()getcustomers2Async() 不完整。 await 关键字允许您在 await 行下方编写代码,等待任务完成后将 运行。在您的情况下,等待行下方没有代码,因此您也可以 return 直接执行任务而不等待它们:

public Task<string> GetCustomers1()
{
    return getcustomer1Async();
}

请注意,不仅 await 关键字消失了,async 也消失了。

至于 Index 方法,它应该给你一个编译时警告,因为在用 async 关键字标记的方法中没有 await。您可能应该将其修改为如下内容:

public async Task<JsonResult> Index()
{
   var task1 = Task.Run(() => GetCustomers1());
   var task2 = Task.Run(() => GetCustomers2());
   string[] results = await Task.WhenAll(task1, task2);
   //...use the results to create a JsonResult and return it
}

最后请记住,通常的做法是将后缀 Async 添加到 return 和 Task 的方法中。所以方法GetCustomers1应该重命名为GetCustomers1Async,方法Index应该重命名为IndexAsync等。你可以阅读相关指南here

I am clear that task run will create two threads to execute methods GetCustomers1, GetCustomers2.

Task.Run 不创建线程。它将工作排队到线程池。

my question is when the method GetCustomers1 and GetCustomers2 reach the line that has the word await, should the incomplete task be returned, where should the incomplete task be returned? Does the thread return to the thread pool?

是,线程返回线程池。当 await 准备好恢复执行时,该方法的 "continuation" 将排队到线程池。请注意,延续可能会也可能不会 运行 在同一线程上;他们可以 运行 在任何线程池线程上。

Task.WaitAll would you have the main thread busy until the other tasks finish running?

是的,这就是 Task.WaitAll 会做的。它还会阻塞异步代码,这不是一个好主意。不如去async all the way.

I know you shouldn't use tak.run if the method is asynchronous.

异步代码使用Task.Run就可以了。但在一般情况下,您不应该在 ASP.NET 上使用 Task.Run,因为它会将工作排队到线程池,而不是让 ASP.NET 完全控制线程池。相反,直接调用异步代码并使用异步代码 (Task.WhenAll) 而不是阻塞代码 (Task.WaitAll):

public async Task<string> GetCustomers1() {
  return await getcustomer1Async();
}
public async Task<string> GetCustomers2(){
  return await getcustomer2Async();
}
public async Task<JsonResult> Index(){
  var result1 = GetCustomers1();
  var result2 = GetCustomers2();
  await Task.WhenAll(result1, result2);
}