ASP.NET Core multithreaded background threads

Using ASP.NET Core .NET 5. Running on Windows.

Users upload large workbooks that need to be converted to a different format. Each conversion process is CPU intensive and takes around a minute to complete.

The idea is to use a pattern where the requests are queued in a background queue and then processed by background tasks.

So, I followed this Microsoft article

The queuing part worked well but the issue was that workbooks were executing sequentially in the background:

private async Task BackgroundProcessing(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        var workItem = 
            await TaskQueue.DequeueAsync(stoppingToken);

        try
        {
            await workItem(stoppingToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, 
                "Error occurred executing {WorkItem}.", nameof(workItem));
        }
    }
}

If I queued 10 workbooks. Workbook 2 wouldn’t start until workbook 1 is done. Workbook 3 wouldn’t start until workbook 2 is done, etc.

So, I modified the code to run tasks without await and hid the warning with the discard operator (please note workItem is now Action, not Task):

while (!stoppingToken.IsCancellationRequested)
{
    var workItem = await TaskQueue.DequeueAsync(stoppingToken);

    _ = Task.Factory.StartNew(() =>
        {
            try
            {
                workItem(stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occurred executing {WorkItem}.", nameof(workItem));
            }
        }, TaskCreationOptions.LongRunning);
}

That works — I get all workbooks starting processing around the same time, and then they complete around the same time too. But, I am not sure if doing this is dangerous and can lead to bugs, crashes, etc.

Is the second version a workable solution, or will it lead to some disaster in the future? Is there a better way to implement parallel workloads on the background threads in ASP.NET?

Thanks.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Using an external queue has some advantages over in-memory queueing. In particular, the queue message are stored in a reliable external store with features around retries, multiple consumers, etc. If your app crashes, the queue item remains and can be tried again.

In Azure, you can use several services including Azure Storage Queues and Service Bus. I like Service Bus because it uses push-based behavior to avoid the need for a polling loop in your code. Either way, you can create an instance of IHostedService that will watch the queue and process the work items in a separate thread with configurable parallelization.

Look for examples on using within ASP.NET Core, for example:

https://damienbod.com/2019/04/23/using-azure-service-bus-queues-with-asp-net-core-services/

Method 2

The idea is to use a pattern where the requests are queued in a background queue and then processed by background tasks.

The proper solution for request-extrinsic code is to use a durable queue with a separate backend processor. Any in-memory solution will lose that work any time the application is shut down (e.g., during a rolling upgrade).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x