In summary. I have ASP.NET Core 6 Rest API project with a BackgroundService that is performing some work every 50 ms. For example:
public class DemoWorker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
// Do work
Console.WriteLine(DateTimeOffset.Now);
await Task.Delay(50, stoppingToken);
}
}
}
Recently, I noted the following issue reported by the ReSharper Dynamic Program Analysis (DPA) worker.
Small Object Heap: Allocated 8.1 MB (8500792 B), max: 100.2 MB (105041568 B) of type System.Threading.TimerQueueTimer by DemoWorker.ExecuteAsync(CancellationToken)
at System.Threading.Tasks.Task.Delay(uint, CancellationToken) at System.Threading.Tasks.Task.Delay(TimeSpan, CancellationToken) at DemoWorker.ExecuteAsync(CancellationToken) in <SOURCE_CODE_FILE_NAME> at System.Threading.ExecutionContext.RunInternal(ExecutionContext, ContextCallback, Object) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1 AsyncStateMachineBox
1<System.__Canon,StartupHook d__3>.MoveNext(Thread) at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox, bool) at System.Threading.Tasks.Task.RunContinuations(Object) at System.Threading.Tasks.Task.TrySetResult() at System.Threading.Tasks.Task DelayPromise.CompleteTimedOut() at System.Threading.TimerQueueTimer.Fire(bool) at System.Threading.TimerQueue.FireNextTimers() at System.Threading.UnmanagedThreadPoolWorkItem.System.Threading.IThreadPoolWorkItem.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading.PortableThreadPool WorkerThread.WorkerThreadStart()
I read several articles on this. Most of them are saying that this is not a problem and I don't need to do anything special, or to dispose the task.
But one of the articles says that If I'm creating Task.Delay() calls faster than they're ending, then I will have a memory leak!
So my question is should I worry about this or just ignore it ?
CodePudding user response:
There is a class for this purpose you can use as well.
var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(50));
while (await timer.WaitForNextTickAsync(stoppingToken))
{
// Do work
Console.WriteLine(DateTimeOffset.Now);
}
But due to the operating system's architecture, time-related tasks are not 0 reliable.
CodePudding user response:
Suggestion: I might rather use the new PeriodicTimer
as it should be memory leak resistant according to this article.