42
42
using System . Collections . Concurrent ;
43
43
using System . Collections . Generic ;
44
44
using System . Linq ;
45
- using System . Threading ;
45
+ using System . Threading . Channels ;
46
46
using System . Threading . Tasks ;
47
47
48
48
using RabbitMQ . Client . Events ;
49
49
using RabbitMQ . Client . Exceptions ;
50
50
using RabbitMQ . Client . Impl ;
51
-
52
- using RabbitMQ . Util ;
53
51
using RabbitMQ . Client . Logging ;
54
52
55
53
namespace RabbitMQ . Client . Framing . Impl
@@ -664,7 +662,7 @@ private void Init(IFrameHandler fh)
664
662
{
665
663
if ( ShouldTriggerConnectionRecovery ( args ) )
666
664
{
667
- _recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . BeginAutomaticRecovery ) ;
665
+ _recoveryLoopCommandQueue . Writer . TryWrite ( RecoveryCommand . BeginAutomaticRecovery ) ;
668
666
}
669
667
} ;
670
668
lock ( _eventLock )
@@ -1243,9 +1241,7 @@ private enum RecoveryConnectionState
1243
1241
private Task _recoveryTask ;
1244
1242
private RecoveryConnectionState _recoveryLoopState = RecoveryConnectionState . Connected ;
1245
1243
1246
- private readonly AsyncConcurrentQueue < RecoveryCommand > _recoveryLoopCommandQueue = new AsyncConcurrentQueue < RecoveryCommand > ( ) ;
1247
- private readonly CancellationTokenSource _recoveryCancellationToken = new CancellationTokenSource ( ) ;
1248
- private readonly TaskCompletionSource < int > _recoveryLoopComplete = new TaskCompletionSource < int > ( ) ;
1244
+ private readonly Channel < RecoveryCommand > _recoveryLoopCommandQueue = Channel . CreateUnbounded < RecoveryCommand > ( new UnboundedChannelOptions { AllowSynchronousContinuations = false , SingleReader = true , SingleWriter = false } ) ;
1249
1245
1250
1246
/// <summary>
1251
1247
/// This is the main loop for the auto-recovery thread.
@@ -1254,21 +1250,22 @@ private async Task MainRecoveryLoop()
1254
1250
{
1255
1251
try
1256
1252
{
1257
- while ( ! _recoveryCancellationToken . IsCancellationRequested )
1253
+ while ( await _recoveryLoopCommandQueue . Reader . WaitToReadAsync ( ) . ConfigureAwait ( false ) )
1258
1254
{
1259
- var command = await _recoveryLoopCommandQueue . DequeueAsync ( _recoveryCancellationToken . Token ) . ConfigureAwait ( false ) ;
1260
-
1261
- switch ( _recoveryLoopState )
1255
+ while ( _recoveryLoopCommandQueue . Reader . TryRead ( out RecoveryCommand command ) )
1262
1256
{
1263
- case RecoveryConnectionState . Connected :
1264
- RecoveryLoopConnectedHandler ( command ) ;
1265
- break ;
1266
- case RecoveryConnectionState . Recovering :
1267
- RecoveryLoopRecoveringHandler ( command ) ;
1268
- break ;
1269
- default :
1270
- ESLog . Warn ( "RecoveryLoop state is out of range." ) ;
1271
- break ;
1257
+ switch ( _recoveryLoopState )
1258
+ {
1259
+ case RecoveryConnectionState . Connected :
1260
+ RecoveryLoopConnectedHandler ( command ) ;
1261
+ break ;
1262
+ case RecoveryConnectionState . Recovering :
1263
+ RecoveryLoopRecoveringHandler ( command ) ;
1264
+ break ;
1265
+ default :
1266
+ ESLog . Warn ( "RecoveryLoop state is out of range." ) ;
1267
+ break ;
1268
+ }
1272
1269
}
1273
1270
}
1274
1271
}
@@ -1280,8 +1277,6 @@ private async Task MainRecoveryLoop()
1280
1277
{
1281
1278
ESLog . Error ( "Main recovery loop threw unexpected exception." , e ) ;
1282
1279
}
1283
-
1284
- _recoveryLoopComplete . SetResult ( 0 ) ;
1285
1280
}
1286
1281
1287
1282
/// <summary>
@@ -1290,8 +1285,10 @@ private async Task MainRecoveryLoop()
1290
1285
/// </summary>
1291
1286
private void StopRecoveryLoop ( )
1292
1287
{
1293
- _recoveryCancellationToken . Cancel ( ) ;
1294
- if ( ! _recoveryLoopComplete . Task . Wait ( _factory . RequestedConnectionTimeout ) )
1288
+ _recoveryLoopCommandQueue . Writer . Complete ( ) ;
1289
+ Task timeout = Task . Delay ( _factory . RequestedConnectionTimeout ) ;
1290
+
1291
+ if ( Task . WhenAny ( _recoveryTask , timeout ) . Result == timeout )
1295
1292
{
1296
1293
ESLog . Warn ( "Timeout while trying to stop background AutorecoveringConnection recovery loop." ) ;
1297
1294
}
@@ -1351,11 +1348,9 @@ private void RecoveryLoopConnectedHandler(RecoveryCommand command)
1351
1348
/// </summary>
1352
1349
private void ScheduleRecoveryRetry ( )
1353
1350
{
1354
- Task . Delay ( _factory . NetworkRecoveryInterval )
1355
- . ContinueWith ( t =>
1356
- {
1357
- _recoveryLoopCommandQueue . Enqueue ( RecoveryCommand . PerformAutomaticRecovery ) ;
1358
- } ) ;
1351
+ _ = Task
1352
+ . Delay ( _factory . NetworkRecoveryInterval )
1353
+ . ContinueWith ( t => _recoveryLoopCommandQueue . Writer . TryWrite ( RecoveryCommand . PerformAutomaticRecovery ) ) ;
1359
1354
}
1360
1355
}
1361
1356
}
0 commit comments