In my project I'm using ASP.NET Core 3.1 with a hosted service background worker.
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var result = await _messageBus.Get();
if (result != null)
{
await _dbContext.UpdateData(result, stoppingToken);
}
await Task.Delay(5000, stoppingToken);
}
}
Inside my DbContext I do some logic then call await command.ExecuteNonQueryAsync(stoppingToken);
. On that line the worker deadlocks.
await using var connection = new SqlConnection(dbConnection);
await connection.OpenAsync(stoppingToken);
var command = connection.CreateCommand();
command.CommandText = query;
await command.ExecuteNonQueryAsync(stoppingToken);
I then changed the background worker to:
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_timer = new Timer(async state => await Run(state, stoppingToken), null,
TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private async Task Run(object state, CancellationToken stoppingToken)
{
var result = await _messageBus.Get();
if (result != null) await _dbContext.UpdateData(result, stoppingToken);
}
This ended up working and avoided a deadlock. However I honestly don't know why this worked and avoided a deadlock. What makes the the Timer
class different than just using Task.Delay
?