You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If I run my code (simplified below) with two different instances locally (dotnet run or VS for the first and dotnet run --no-build for the second) and restart my db a couple of times odds are quite high that eventually an instance will just keep going without the lock (in the while-loop). It could be as few restarts as 3-4 restarts. My understanding where that when you access handle.HandleLostToken.IsCancellationRequested it will make sure that the lock still exists? Or is that not working together with CancellationTokenSource.CreateLinkedTokenSource? I just tried without CancellationTokenSource.CreateLinkedTokenSource and get the same result. Not sure what is going on...
usingMedallion.Threading;namespaceSample;publicclassTestBackgroundService:BackgroundService{privatereadonlyIServiceScopeFactory_serviceScopeFactory;privatereadonlyILogger<TestBackgroundService>_logger;publicTestBackgroundService(IServiceScopeFactoryserviceScopeFactory,ILogger<TestBackgroundService>logger){_serviceScopeFactory=serviceScopeFactory;_logger=logger;}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){while(!stoppingToken.IsCancellationRequested){try{awaitusingvarscope=_serviceScopeFactory.CreateAsyncScope();vardistributedLockProvider=scope.ServiceProvider.GetRequiredService<IDistributedLockProvider>();_logger.LogInformation("Will try to acquire lock.");awaitusingvarhandle=awaitdistributedLockProvider.AcquireLockAsync("a1416b2940b34bbb9189caaa13f11b1a",cancellationToken:stoppingToken);_logger.LogInformation("Acquired lock.");handle.HandleLostToken.Register(()=>_logger.LogError("Lost lock for job {Job Name}.",nameof(TestBackgroundService)));varstoppingCts=CancellationTokenSource.CreateLinkedTokenSource(stoppingToken,handle.HandleLostToken);if(stoppingCts.Token.IsCancellationRequested){return;}while(!stoppingCts.IsCancellationRequested)// This evaluates to true sometimes even if the database has been restarted{_logger.LogInformation("Doing stuff.");try{awaitTask.Delay(TimeSpan.FromSeconds(30),stoppingCts.Token);}catch(TaskCanceledException){}}}catch(Exceptionex){_logger.LogError(ex,"Something went wrong.");}}}}
Update: I can replicate it with just one instance (even if the log gets a bit tricker to follow then):
usingMedallion.Threading;namespaceSamples;publicsealedclassJob1:JobBase{publicJob1(IServiceScopeFactoryserviceScopeFactory,ILogger<Job1>logger):base(serviceScopeFactory,logger){}}publicsealedclassJob2:JobBase{publicJob2(IServiceScopeFactoryserviceScopeFactory,ILogger<Job2>logger):base(serviceScopeFactory,logger){}}publicabstractclassJobBase:BackgroundService{privatereadonlyIServiceScopeFactory_serviceScopeFactory;privatereadonlyILogger_logger;publicJobBase(IServiceScopeFactoryserviceScopeFactory,ILoggerlogger){_serviceScopeFactory=serviceScopeFactory;_logger=logger;}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){while(!stoppingToken.IsCancellationRequested){try{awaitusingvarscope=_serviceScopeFactory.CreateAsyncScope();vardistributedLockProvider=scope.ServiceProvider.GetRequiredService<IDistributedLockProvider>();_logger.LogInformation("Will try to acquire lock.");awaitusingvarhandle=awaitdistributedLockProvider.AcquireLockAsync("a1416b2940b34bbb9189caaa13f11b1a",cancellationToken:stoppingToken);_logger.LogInformation("Acquired {CancelableDescription} lock.",handle.HandleLostToken.CanBeCanceled?"cancelable":"uncancelable");awaitusingvar_=handle.HandleLostToken.Register(()=>_logger.LogError("Lost lock."));usingvarstoppingCts=CancellationTokenSource.CreateLinkedTokenSource(stoppingToken,handle.HandleLostToken);if(stoppingCts.Token.IsCancellationRequested){return;}while(!stoppingCts.IsCancellationRequested)// This evaluates to true sometimes even if the database has been restarted{_logger.LogInformation("Doing stuff.");try{awaitTask.Delay(TimeSpan.FromSeconds(30),stoppingCts.Token);}catch(TaskCanceledException){}if(!stoppingToken.IsCancellationRequested){_logger.LogInformation("Cancellation is not requested.");}}}catch(Exceptionexception){_logger.LogError("Exception {Exception} thrown.",exception.GetType());}}}}
If I run my code (simplified below) with two different instances locally (
dotnet runor VS for the first anddotnet run --no-buildfor the second) and restart my db a couple of times odds are quite high that eventually an instance will just keep going without the lock (in the while-loop). It could be as few restarts as 3-4 restarts. My understanding where that when you accesshandle.HandleLostToken.IsCancellationRequestedit will make sure that the lock still exists?Or is that not working together withI just tried withoutCancellationTokenSource.CreateLinkedTokenSource?CancellationTokenSource.CreateLinkedTokenSourceand get the same result. Not sure what is going on...Update: I can replicate it with just one instance (even if the log gets a bit tricker to follow then):