在 ASP.Net 核心中使用 Task.Run

Using Task.Run in ASP.Net Core

我读过这些文章:

ASP.NET Core Performance Best Practices

docs.microsoft的第一篇文章中我们可以看到这样的说法:

Call data access, I/O, and long-running operations APIs asynchronously if an asynchronous API is available. Do not use Task.Run to make a synchronous API asynchronous.

我不是很理解这个说法。我对何时何地应该使用 Task.Run 以及何时何地应该(可以)编写异步 Web API 感到困惑。例如,考虑这个方法:

public int DoSomeHeavyWork()
{
   // Consider heavy computations
   int i = 10;
   i = i * 2;
   i = i + 4;
   return i;
}

和这个方法:

public void SaveSomthingInDb(Order ord)
{
    _dbContext.Orders.Add(ord);
    _dbContext.SaveChange();
}

按照上面的说法,我应该同步写一个web方法,因为没有async版本:

public IActionResult API_DoSomeHeavyWork()
{
    return Ok(DoSomeHeavyWork());
}

但对于方法 2,我可以这样更改:

public async Task SaveSomthingInDbAsync(Order ord)
{
    _dbContext.Orders.Add(ord);
    await _dbContext.SaveChangeAsync();
}

所以我可以这样写 API:

public async Task<IActionResult> API_SaveSomthingInDbAsync(Order ord)
{
    await SaveSomthingInDbAsync(ord);
    return Ok("Object Added");
}

我不知道我对这个问题的看法是否正确?写这些方法是真的吗?有什么办法运行第一个APIasync?

谢谢


编辑 1)

感谢“Stephen Cleary”。

如果我们假设这句话:我们在Web的web方法中使用async方法API来防止阻塞线程池线程并接受更多的请求...

请考虑此代码:

await _context.Order.ToListAsync();

根据这段代码,有一个名为 Microsoft.EntityFrameworkCore 的程序集,它有一个名为 ToListAsync:

async 方法
public static Task<List<TSource>> ToListAsync<TSource>(this IQueryable<TSource> source, CancellationToken cancellationToken = default(CancellationToken))

第一个问题是ToListAsync是如何实现的?是这样实现的吗?

public static Task<List<TSource>> ToListAsync<TSource>(...)
{
    Task.Run(()=>{ <Some thing>.ToList() });
}

第二个问题是方法 DoSomeHeavyWork 是否放在单独的程序集中并重写为:

public Task<int> DoSomeHeavyWork()
{
   Task.Run(() => 
   {
       // Consider heavy computations
       int i = 10;
       i = i * 2;
       i = i + 4;
       return i;
   }
}

然后我可以从我的网站 API 和空闲线程池线程中调用它 async 吗?

谢谢

I'm confused about where and when I should use Task.Run

在 ASP.NET 上,几乎从不。您可以采用“从不”作为一般规则。

and where and when I should (can) write async web API.

当且仅当它们调用异步代码时,您的控制器操作才应该是异步的。一般来说,对于执行 I/O 的所有代码,您应该更喜欢最低级别的异步 API。然后你的操作方法只有在需要调用异步代码时才是异步的。

I should write a web method synchronously because there is no async version ... but for method 2 I can change it this way

是的。

Is there any way to run the first API async?

想一想 this way:如果有同步 (CPU-bound) 工作要做,那么该工作需要一个线程。它已经在线程池线程上 运行ning(因为网络请求 运行 来自线程的线程 水池)。 Task.Run 会将工作转移到不同的线程池线程,但它仍会 运行 在线程池线程上。所以 Task.Run 没有任何帮助;它只会增加开销而不会带来任何好处。因此一般规则“不要在 ASP.NET 上使用 Task.Run”。