@@ -37,7 +37,8 @@ public class GeneralClientBootstrap : AbstractBootstrap<GeneralClientBootstrap,
3737 private readonly List < Func < bool > > _customOptions = new ( ) ;
3838 private volatile bool _launchSilentUpdaterOnExit ;
3939 private bool _silentUpdaterLaunched ;
40- private SilentVersionPollingTimer ? _silentVersionPollingTimer ;
40+ private CancellationTokenSource ? _silentVersionPollingCts ;
41+ private Task ? _silentVersionPollingTask ;
4142 private int _pollingExitHookRegistered ;
4243 private int _workflowExecuting ;
4344 private readonly object _silentUpdateLock = new ( ) ;
@@ -383,30 +384,24 @@ private void ScheduleSilentMainUpdate()
383384
384385 private void StartSilentVersionPolling ( )
385386 {
386- if ( _silentVersionPollingTimer != null || _launchSilentUpdaterOnExit || _configInfo == null )
387+ if ( _silentVersionPollingTask != null || _launchSilentUpdaterOnExit || _configInfo == null )
387388 {
388389 return ;
389390 }
390391
391- _silentVersionPollingTimer = new SilentVersionPollingTimer (
392- async ( ) => await ExecuteWorkflowWithReentryGuardAsync ( ) ,
393- SilentVersionPollingInterval ,
394- exception =>
395- {
396- GeneralTracer . Error ( "Silent update polling loop failed." , exception ) ;
397- EventManager . Instance . Dispatch ( this , new ExceptionEventArgs ( exception , exception . Message ) ) ;
398- } ) ;
392+ _silentVersionPollingCts = new CancellationTokenSource ( ) ;
393+ _silentVersionPollingTask = RunSilentVersionPollingLoopAsync ( _silentVersionPollingCts . Token ) ;
399394 if ( Interlocked . CompareExchange ( ref _pollingExitHookRegistered , 1 , 0 ) == 0 )
400395 {
401396 AppDomain . CurrentDomain . ProcessExit += OnPollingProcessExit ;
402397 }
403- _silentVersionPollingTimer . Start ( ) ;
404398 }
405399
406400 private void StopSilentVersionPolling ( )
407401 {
408- var timer = Interlocked . Exchange ( ref _silentVersionPollingTimer , null ) ;
409- timer ? . Dispose ( ) ;
402+ var cts = Interlocked . Exchange ( ref _silentVersionPollingCts , null ) ;
403+ cts ? . Cancel ( ) ;
404+ cts ? . Dispose ( ) ;
410405 if ( Interlocked . CompareExchange ( ref _pollingExitHookRegistered , 0 , 1 ) == 1 )
411406 {
412407 AppDomain . CurrentDomain . ProcessExit -= OnPollingProcessExit ;
@@ -415,6 +410,36 @@ private void StopSilentVersionPolling()
415410
416411 private void OnPollingProcessExit ( object ? sender , EventArgs e ) => StopSilentVersionPolling ( ) ;
417412
413+ private async Task RunSilentVersionPollingLoopAsync ( CancellationToken cancellationToken )
414+ {
415+ try
416+ {
417+ while ( ! cancellationToken . IsCancellationRequested && ! _launchSilentUpdaterOnExit )
418+ {
419+ await Task . Delay ( SilentVersionPollingInterval , cancellationToken ) ;
420+ if ( _launchSilentUpdaterOnExit )
421+ {
422+ break ;
423+ }
424+
425+ await ExecuteWorkflowWithReentryGuardAsync ( ) ;
426+ }
427+ }
428+ catch ( OperationCanceledException )
429+ {
430+ // Ignore cancellation.
431+ }
432+ catch ( Exception exception )
433+ {
434+ GeneralTracer . Error ( "Silent update polling loop failed." , exception ) ;
435+ EventManager . Instance . Dispatch ( this , new ExceptionEventArgs ( exception , exception . Message ) ) ;
436+ }
437+ finally
438+ {
439+ Interlocked . Exchange ( ref _silentVersionPollingTask , null ) ;
440+ }
441+ }
442+
418443 private void OnCurrentDomainProcessExit ( object ? sender , EventArgs e )
419444 {
420445 lock ( _silentUpdateLock )
0 commit comments