Search code examples
asp.net-coreasynchronousioopenxmlc#-6.0

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


My ASP.NET core application uses Entity Framework Core. As you would expect must controller methods are async and call async methods of EF Core.

I also have controller methods thats need to read from and write to excel files. I'm using OpenXml. Since these are IO operation, ideally I they would be an async operation but OpenXml doesn't offer any async methods. Here is a simplified example

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;
}

Also, I need to find the file in a folder first which I would also like to make async.

Directory.EnumerateFiles("excelFolderName", ".xlsx");

According to this document ASP.NET Core Performance Best Practices I shouldn't use Task.Run to make an synchronous API asynchronous. I understand why but does that rule apply to IO operations which will block the thread potential for a few seconds? Should I make these IO operations async and if so what is the base way to make reading and writing excel file and getting file list asynchronous?


Solution

  • Since these are IO operation, ideally I they would be an async operation but OpenXml doesn't offer any async methods.

    Also, I need to find the file in a folder first which I would also like to make async.

    Ideally, those would be asynchronous APIs. But they're not. The way to make them asynchronous is to fix the API, not wrap it in Task.Run. You can open a request with the maintainers of OpenXml for asynchronous APIs. The file system operation is more awkward; it's a Win32 limitation, not a BCL limitation, and it's unlikely to be fixed, but you can ask.

    does that rule apply to IO operations which will block the thread potential for a few seconds?

    Yes.

    The request is blocked for the same amount of time whether it's synchronous or asynchronous. So the thing to consider is how threads are blocked. In the ideal asynchronous case, no threads are blocked. Since you only have synchronous APIs, you do have to block a thread; calling the API directly will block a thread pool thread, and shoving it off to Task.Run will block a different thread pool thread - which is pointless.

    Should I make these IO operations async and if so what is the base way to make reading and writing excel file and getting file list asynchronous?

    You can't "make them async". You can request async APIs and then use the synchronous ones for now.