„timer + Task.Run“ vs. „while loop + Task.Delay“ im von asp.net gehosteten KerndienstC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 „timer + Task.Run“ vs. „while loop + Task.Delay“ im von asp.net gehosteten Kerndienst

Post by Anonymous »

Ich habe die Anforderung, dass der Hintergrunddienst die Process-Methode jeden Tag um 0:00 Uhr ausführen soll.
Also hat eines meiner Teammitglieder den folgenden Code geschrieben:

Code: Select all

public class MyBackgroundService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private Timer _timer;

public MyBackgroundService(ILogger logger)
{
_logger = logger;
}

public void Dispose()
{
_timer?.Dispose();
}

public Task StartAsync(CancellationToken cancellationToken)
{
TimeSpan interval = TimeSpan.FromHours(24);
TimeSpan firstCall = DateTime.Today.AddDays(1).AddTicks(-1).Subtract(DateTime.Now);

Action action = () =>
{
Task.Delay(firstCall).Wait();

Process();

_timer = new Timer(
ob => Process(),
null,
TimeSpan.Zero,
interval
);
};

Task.Run(action);
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);

return Task.CompletedTask;
}

private Task Process()
{
try
{
// perform some database operations
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
}
return Task.CompletedTask;
}
}
Dieser Code funktioniert wie erwartet. Aber mir gefällt nicht, dass es synchron wartet, bis Process zum ersten Mal aufgerufen wird, sodass ein Thread blockiert wird und keine nützliche Arbeit ausführt (korrigieren Sie mich, wenn ich falsch liege).
Ich könnte eine Aktion asynchron machen und darin warten, wie folgt:

Code: Select all

public Task StartAsync(CancellationToken cancellationToken)
{
// code omitted for brevity

Action action = async () =>
{
await Task.Delay(firstCall);

await Process();

// code omitted for brevity
}
Aber ich bin mir nicht sicher, ob die Verwendung von Task.Run hier eine gute Sache ist, da die Process-Methode einige E/A-Vorgänge ausführen soll (Datenbank abfragen und einige Daten einfügen), und weil es nicht empfohlen wird, Task.Run in einer ASP.NET-Umgebung zu verwenden.
Ich habe StartAsync wie folgt umgestaltet:

Code: Select all

public async Task StartAsync(CancellationToken cancellationToken)
{
TimeSpan interval = TimeSpan.FromHours(24);
TimeSpan firstDelay = DateTime.Today.AddDays(1).AddTicks(-1).Subtract(DateTime.Now);

await Task.Delay(firstDelay);

while (!cancellationToken.IsCancellationRequested)
{
await Process();

await Task.Delay(interval, cancellationToken);
}
}
Und dadurch kann ich den Timer in MyBackgroundService überhaupt nicht verwenden.
Soll ich den ersten Ansatz mit „timer + Task.Run“ oder den zweiten mit „while loop + Task.Delay“ verwenden?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post