ASP.NET 核心和 C#。如何异步运行同步方法

ASP.NET core & C#. How to run a synchronous method asynchronously

提问人:JHJ 提问时间:11/14/2022 最后编辑:JHJ 更新时间:11/14/2022 访问量:562

问:

我的 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 文件和获取文件列表异步的基本方法是什么?

ASP.Net-Core 异步 IO OpenXML C#-6.0

评论

0赞 Patrick Beynio 11/14/2022
ASP 不会在 UI 线程上运行操作,听起来你必须按顺序做一些事情,所以我认为你应该听听那里的文档......
1赞 Patrick Beynio 11/14/2022
文档试图告诉你的是,你不会从可以内联的方法中受益,它只会导致无用的调度。await Task.Run(...);

答:

2赞 Stephen Cleary 11/14/2022 #1

由于这些是 IO 操作,理想情况下,它们将是异步操作,但 OpenXml 不提供任何异步方法。

另外,我需要首先在一个文件夹中找到文件,我也想进行异步。

理想情况下,这些是异步 API。但事实并非如此。使它们异步的方法是修复 API,而不是将其包装在 .您可以向 OpenXml 的维护者提出异步 API 请求。文件系统操作比较笨拙;这是 Win32 限制,而不是 BCL 限制,而且不太可能修复,但你可以问。Task.Run

该规则是否适用于会阻塞线程电位几秒钟的 IO 操作?

是的。

无论请求是同步的还是异步的,都会阻止相同的时间。因此,要考虑的是如何阻止线程。在理想的异步情况下,不会阻塞任何线程。由于您只有同步 API,因此您必须阻止线程;直接调用 API 将阻止线程池线程,将其推送到将阻止另一个线程池线程 - 这是没有意义的。Task.Run

我是否应该使这些 IO 操作异步,如果是这样,使读取和写入 excel 文件和获取文件列表异步的基本方法是什么?

你不能“使它们异步”。您可以请求异步 API,然后暂时使用同步 API。

评论

0赞 JHJ 11/15/2022
是的。这就是我的想法,但我不得不问。