0

I am not entirely new to using async/await in C#, but certainly have not done a ton of it by any means. I am looking to find out how much async code to write based on a certain scenario. The scenario is as follows:

.NET Core Web Api with controller and one async Get() function:

[ApiController]
[Route("api/[controller]")]
public class ThingController
{
    private readonly IThingFetchService _thingFetchService;

    public ThingController(IThingFetchService thingFetchService)
    {
        _thingFetchService = thingFetchService;
    }

    public async Task<ActionResult<ThingSummary>> Get()
    {
        return await _thingFetchService.GetDataAsync();
    }
}

Here is the call into the service layer (IThingFetchService):

public class ThingFetchService : IThingFetchService
{
    private readonly IApiDataFetcher _dataFetcher;
    private readonly  IChartDetailBuilder _chartDetailBuilder;

    public ThingFetchService(IApiDataFetcher dataFetcher, IChartDetailBuilder chartDetailBuilder)
    {            
        _dataFetcher = dataFetcher;
        _chartDetailBuilder = chartDetailBuilder;
    }

    public async Task<ThingSummary> GetDataAsync()
    {
        var things = await _dataFetcher.GetDataAsync<Thing>(); // returns IEnumerable<Thing> from an external API

        // NOTE: THIS IS WHAT THE QUESTION IS ABOUT:
        // Should this call be async, even though it is just crunching the data already fetched? (i.e. no I/O or anything, just processing
        // and crunching data into new data points for a chart)
        var chartDetails = _chartDetailBuilder.GetChartDetails(things);

        return new ThingSummary {
            Things = things,
            ChartDetails = chartDetails
        }
    }
}

And just for full reference, the service that gets called that the question is all about:

public class ChartDetailBuilder : IChartDetailBuilder {

    // should this be async? 
    public IEnumerable<ChartDetail> GetChartDetails(IEnumerable<Thing> things) {
        var details = new List<ChartDetail>();

        foreach(var thing in things) {
            // do something sort of tedious, potentially intensive to get a data point from a Thing object
            details.Add(new ChartDetail {
                X = 1,
                Y = 1
            }); 
        }

        return details;
    }
}

Long story short here: I want to know if the IChartDetailBuilder.GetChartDetails(IEnumerable<Thing> things) method should be async or not or if it matters in the context of being called from an async method? I guess I am specifically looking at this in the context of .NET Web API but any feedback is genuinely appreciated.

efischency
  • 473
  • 2
  • 14
  • 1
    @MatthewWatson But in an ASP.NET environment that achieves nothing: it will just block another thread in the thread-pool. In fact it will negatively impact performance. – Johnathan Barclay Jul 28 '20 at 14:57
  • 3
    @JohnathanBarclay Ah good point - what I said only applies to UI-based code. – Matthew Watson Jul 28 '20 at 15:00
  • 2
    So for an ASP.Net application, you should just write the code like you have - do NOT try to make the CPU-bound operation asynchronous via something like `Task.Run()`. (If, however, this was a Windows Forms or a WPF app, you may well want to use `Task.Run()` to stop the UI from blocking.) – Matthew Watson Jul 28 '20 at 15:09
  • @MatthewWatson so are you saying that having the chart detail "crunching" stuff synchronous is perfectly fine and actually preferred here? Is that because it is not going to do anything that would even allow for a thread to be released, like I/O or something like that? – efischency Jul 28 '20 at 15:38
  • 1
    @efischency Yes - there is no UI thread to get blocked, so all that happens is that the page takes longer to update in the browser. Spinning off a new thread to perform the CPU-bound operation will not make it any faster, and will in fact use up a thread pointlessly. – Matthew Watson Jul 28 '20 at 16:00
  • @MatthewWatson thanks - just one more clarification - what is the difference if I happened to make that `GetChartDetails` method async (like with the keyword), but just called it with `await` like I do with the `FetchDataAsync` method.. because it is not doing any I/O and thus _needs_ the thread to process the data, does it make no difference at that point? – efischency Jul 28 '20 at 16:09

0 Answers0