提问人:JHJ 提问时间:11/14/2022 最后编辑:JHJ 更新时间:11/14/2022 访问量:562
ASP.NET 核心和 C#。如何异步运行同步方法
ASP.NET core & C#. How to run a synchronous method asynchronously
问:
我的 ASP.NET 核心应用程序使用 Entity Framework Core。如你所料,控制器方法必须是异步的,并调用 EF Core 的异步方法。
我还有需要读取和写入 excel 文件的控制器方法。我正在使用 OpenXml。由于这些是 IO 操作,理想情况下,它们将是异步操作,但 OpenXml 不提供任何异步方法。下面是一个简化的例子
private async Task<model> ReadFromExcel()
{
using var document = SpreadsheetDocument.Open("filePathAndName", false);
// read data into model
document.Close();
context.Models.Add(newModel);
await Context.SaveAsync();
return newModel;
}
另外,我需要首先在一个文件夹中找到文件,我也想进行异步。
Directory.EnumerateFiles("excelFolderName", ".xlsx");
根据 ASP.NET 核心性能最佳实践的文档,我不应该使用 Task.Run 来使同步 API 异步。我明白为什么,但该规则是否适用于会阻塞线程电位几秒钟的 IO 操作?我是否应该使这些 IO 操作异步,如果是这样,使读取和写入 excel 文件和获取文件列表异步的基本方法是什么?
答:
由于这些是 IO 操作,理想情况下,它们将是异步操作,但 OpenXml 不提供任何异步方法。
另外,我需要首先在一个文件夹中找到文件,我也想进行异步。
理想情况下,这些是异步 API。但事实并非如此。使它们异步的方法是修复 API,而不是将其包装在 .您可以向 OpenXml 的维护者提出异步 API 请求。文件系统操作比较笨拙;这是 Win32 限制,而不是 BCL 限制,而且不太可能修复,但你可以问。Task.Run
该规则是否适用于会阻塞线程电位几秒钟的 IO 操作?
是的。
无论请求是同步的还是异步的,都会阻止相同的时间。因此,要考虑的是如何阻止线程。在理想的异步情况下,不会阻塞任何线程。由于您只有同步 API,因此您必须阻止线程;直接调用 API 将阻止线程池线程,将其推送到将阻止另一个线程池线程 - 这是没有意义的。Task.Run
我是否应该使这些 IO 操作异步,如果是这样,使读取和写入 excel 文件和获取文件列表异步的基本方法是什么?
你不能“使它们异步”。您可以请求异步 API,然后暂时使用同步 API。
评论
await Task.Run(...);