14
14
*/
15
15
16
16
using System ;
17
+ using System . Collections . Concurrent ;
17
18
using System . Diagnostics ;
18
19
using System . Net ;
19
20
using System . Threading ;
20
- using System . Threading . Tasks ;
21
21
using MongoDB . Bson ;
22
22
using MongoDB . Driver . Core . Connections ;
23
23
using MongoDB . Driver . Core . Events ;
@@ -43,6 +43,8 @@ internal sealed class ServerMonitor : IServerMonitor
43
43
private readonly InterlockedInt32 _state ;
44
44
private readonly ServerMonitorSettings _serverMonitorSettings ;
45
45
46
+ private Thread _serverMonitorThread ;
47
+
46
48
private readonly Action < ServerHeartbeatStartedEvent > _heartbeatStartedEventHandler ;
47
49
private readonly Action < ServerHeartbeatSucceededEvent > _heartbeatSucceededEventHandler ;
48
50
private readonly Action < ServerHeartbeatFailedEvent > _heartbeatFailedEventHandler ;
@@ -144,15 +146,21 @@ public void Initialize()
144
146
{
145
147
if ( _state . TryChange ( State . Initial , State . Open ) )
146
148
{
147
- // the call to Task.Factory.StartNew is not normally recommended or necessary
148
- // we are using it temporarily to work around a race condition in some of our tests
149
- // the issue is that we set up some mocked async methods to return results immediately synchronously
150
- // which results in the MonitorServerAsync method making more progress synchronously than the test expected
151
- // by using Task.Factory.StartNew we introduce a short delay before the MonitorServerAsync Task starts executing
152
- // the delay is whatever time it takes for the new Task to be activated and scheduled
153
- // and the delay is usually long enough for the test to get past the race condition (though not guaranteed)
154
- _ = Task . Factory . StartNew ( ( ) => _ = MonitorServerAsync ( ) . ConfigureAwait ( false ) ) . ConfigureAwait ( false ) ;
155
- _ = _roundTripTimeMonitor . RunAsync ( ) . ConfigureAwait ( false ) ;
149
+ _roundTripTimeMonitor . Start ( ) ;
150
+ _serverMonitorThread = new Thread ( ThreadStart ) { IsBackground = true } ;
151
+ _serverMonitorThread . Start ( ) ;
152
+ }
153
+
154
+ void ThreadStart ( )
155
+ {
156
+ try
157
+ {
158
+ MonitorServer ( ) ;
159
+ }
160
+ catch ( OperationCanceledException )
161
+ {
162
+ // ignore OperationCanceledException
163
+ }
156
164
}
157
165
}
158
166
@@ -187,7 +195,7 @@ private CommandWireProtocol<BsonDocument> InitializeHelloProtocol(IConnection co
187
195
return HelloHelper . CreateProtocol ( helloCommand , _serverApi , commandResponseHandling ) ;
188
196
}
189
197
190
- private async Task < IConnection > InitializeConnectionAsync ( CancellationToken cancellationToken ) // called setUpConnection in spec
198
+ private IConnection InitializeConnection ( CancellationToken cancellationToken ) // called setUpConnection in spec
191
199
{
192
200
var connection = _connectionFactory . CreateConnection ( _serverId , _endPoint ) ;
193
201
@@ -196,7 +204,7 @@ private async Task<IConnection> InitializeConnectionAsync(CancellationToken canc
196
204
{
197
205
// if we are cancelling, it's because the server has
198
206
// been shut down and we really don't need to wait.
199
- await connection . OpenAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
207
+ connection . Open ( cancellationToken ) ;
200
208
}
201
209
catch
202
210
{
@@ -210,7 +218,7 @@ private async Task<IConnection> InitializeConnectionAsync(CancellationToken canc
210
218
return connection ;
211
219
}
212
220
213
- private async Task MonitorServerAsync ( )
221
+ private void MonitorServer ( )
214
222
{
215
223
var metronome = new Metronome ( _serverMonitorSettings . HeartbeatInterval ) ;
216
224
var monitorCancellationToken = _monitorCancellationTokenSource . Token ;
@@ -227,7 +235,7 @@ private async Task MonitorServerAsync()
227
235
228
236
try
229
237
{
230
- await HeartbeatAsync ( cachedHeartbeatCancellationToken ) . ConfigureAwait ( false ) ;
238
+ Heartbeat ( cachedHeartbeatCancellationToken ) ;
231
239
}
232
240
catch ( OperationCanceledException ) when ( cachedHeartbeatCancellationToken . IsCancellationRequested )
233
241
{
@@ -244,7 +252,7 @@ private async Task MonitorServerAsync()
244
252
{
245
253
handler . Invoke ( new SdamInformationEvent ( ( ) =>
246
254
string . Format (
247
- "Unexpected exception in ServerMonitor.MonitorServerAsync : {0}" ,
255
+ "Unexpected exception in ServerMonitor.MonitorServer : {0}" ,
248
256
unexpectedException . ToString ( ) ) ) ) ;
249
257
}
250
258
catch
@@ -276,7 +284,7 @@ private async Task MonitorServerAsync()
276
284
}
277
285
_heartbeatDelay = newHeartbeatDelay ;
278
286
}
279
- await newHeartbeatDelay . Task . ConfigureAwait ( false ) ; // corresponds to wait method in spec
287
+ newHeartbeatDelay . Wait ( monitorCancellationToken ) ; // corresponds to wait method in spec
280
288
}
281
289
catch
282
290
{
@@ -285,7 +293,7 @@ private async Task MonitorServerAsync()
285
293
}
286
294
}
287
295
288
- private async Task HeartbeatAsync ( CancellationToken cancellationToken )
296
+ private void Heartbeat ( CancellationToken cancellationToken )
289
297
{
290
298
CommandWireProtocol < BsonDocument > helloProtocol = null ;
291
299
bool processAnother = true ;
@@ -304,7 +312,7 @@ private async Task HeartbeatAsync(CancellationToken cancellationToken)
304
312
}
305
313
if ( connection == null )
306
314
{
307
- var initializedConnection = await InitializeConnectionAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
315
+ var initializedConnection = InitializeConnection ( cancellationToken ) ;
308
316
lock ( _lock )
309
317
{
310
318
if ( _state . Value == State . Disposed )
@@ -326,7 +334,7 @@ private async Task HeartbeatAsync(CancellationToken cancellationToken)
326
334
{
327
335
helloProtocol = InitializeHelloProtocol ( connection , previousDescription ? . HelloOk ?? false ) ;
328
336
}
329
- heartbeatHelloResult = await GetHelloResultAsync ( connection , helloProtocol , cancellationToken ) . ConfigureAwait ( false ) ;
337
+ heartbeatHelloResult = GetHelloResult ( connection , helloProtocol , cancellationToken ) ;
330
338
}
331
339
}
332
340
catch ( OperationCanceledException ) when ( cancellationToken . IsCancellationRequested )
@@ -420,7 +428,7 @@ bool IsNetworkError(Exception ex)
420
428
}
421
429
}
422
430
423
- private async Task < HelloResult > GetHelloResultAsync (
431
+ private HelloResult GetHelloResult (
424
432
IConnection connection ,
425
433
CommandWireProtocol < BsonDocument > helloProtocol ,
426
434
CancellationToken cancellationToken )
@@ -434,7 +442,7 @@ private async Task<HelloResult> GetHelloResultAsync(
434
442
try
435
443
{
436
444
var stopwatch = Stopwatch . StartNew ( ) ;
437
- var helloResult = await HelloHelper . GetResultAsync ( connection , helloProtocol , cancellationToken ) . ConfigureAwait ( false ) ;
445
+ var helloResult = HelloHelper . GetResult ( connection , helloProtocol , cancellationToken ) ;
438
446
stopwatch . Stop ( ) ;
439
447
440
448
if ( _heartbeatSucceededEventHandler != null )
0 commit comments