Skip to content

Commit c33f89c

Browse files
committed
Change "reaper" background task to use PeriodicTimer.
1 parent 6ebfc50 commit c33f89c

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

src/MySqlConnector/Core/ConnectionPool.cs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Concurrent;
2+
using System.Diagnostics;
23
using System.Net;
34
using System.Security.Authentication;
45
using MySqlConnector.Logging;
@@ -551,27 +552,50 @@ private ConnectionPool(ConnectionSettings cs)
551552

552553
private void StartReaperTask()
553554
{
554-
if (ConnectionSettings.ConnectionIdleTimeout > 0)
555+
if (ConnectionSettings.ConnectionIdleTimeout <= 0)
556+
return;
557+
558+
var reaperInterval = TimeSpan.FromSeconds(Math.Max(1, Math.Min(60, ConnectionSettings.ConnectionIdleTimeout / 2)));
559+
560+
#if NET6_0_OR_GREATER
561+
m_reaperTimer = new PeriodicTimer(reaperInterval);
562+
_ = RunTimer();
563+
564+
async Task RunTimer()
555565
{
556-
var reaperInterval = TimeSpan.FromSeconds(Math.Max(1, Math.Min(60, ConnectionSettings.ConnectionIdleTimeout / 2)));
557-
m_reaperTask = Task.Run(async () =>
566+
while (await m_reaperTimer.WaitForNextTickAsync().ConfigureAwait(false))
558567
{
559-
while (true)
568+
try
560569
{
561-
var task = Task.Delay(reaperInterval);
562-
try
563-
{
564-
using var source = new CancellationTokenSource(reaperInterval);
565-
await ReapAsync(IOBehavior.Asynchronous, source.Token).ConfigureAwait(false);
566-
}
567-
catch
568-
{
569-
// do nothing; we'll try to reap again
570-
}
571-
await task.ConfigureAwait(false);
570+
using var source = new CancellationTokenSource(reaperInterval);
571+
await ReapAsync(IOBehavior.Asynchronous, source.Token).ConfigureAwait(false);
572572
}
573-
});
573+
catch
574+
{
575+
// do nothing; we'll try to reap again
576+
}
577+
}
574578
}
579+
#else
580+
m_reaperTimer = new Timer(t =>
581+
{
582+
var stopwatch = Stopwatch.StartNew();
583+
try
584+
{
585+
using var source = new CancellationTokenSource(reaperInterval);
586+
ReapAsync(IOBehavior.Synchronous, source.Token).GetAwaiter().GetResult();
587+
}
588+
catch
589+
{
590+
// do nothing; we'll try to reap again
591+
}
592+
593+
// restart the timer, accounting for the time spent reaping
594+
var delay = reaperInterval - stopwatch.Elapsed;
595+
((Timer) t!).Change(delay < TimeSpan.Zero ? TimeSpan.Zero : delay, TimeSpan.FromMilliseconds(-1));
596+
});
597+
m_reaperTimer.Change(reaperInterval, TimeSpan.FromMilliseconds(-1));
598+
#endif
575599
}
576600

577601
private void StartDnsCheckTimer()
@@ -717,13 +741,14 @@ private static void OnAppDomainShutDown(object? sender, EventArgs e) =>
717741
private readonly Dictionary<string, int>? m_hostSessions;
718742
private readonly object[] m_logArguments;
719743
private int m_generation;
720-
private Task? m_reaperTask;
721744
private uint m_lastRecoveryTime;
722745
private int m_lastSessionId;
723746
private Dictionary<string, CachedProcedure?>? m_procedureCache;
724747
#if NET6_0_OR_GREATER
725748
private PeriodicTimer? m_dnsCheckTimer;
749+
private PeriodicTimer? m_reaperTimer;
726750
#else
727751
private Timer? m_dnsCheckTimer;
752+
private Timer? m_reaperTimer;
728753
#endif
729754
}

0 commit comments

Comments
 (0)