Skip to content

Commit f09dbbc

Browse files
DmitryLukyanovrstam
authored andcommitted
CSHARP-3182: Getting timeout error when using driver in WinForms .net core 3.1 project.
1 parent 693ac5b commit f09dbbc

File tree

3 files changed

+20
-9
lines changed

3 files changed

+20
-9
lines changed

src/MongoDB.Driver.Core/Core/Servers/RoundTripTimeMonitor.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ public void Dispose()
8484

8585
public async Task RunAsync()
8686
{
87-
await Task.Yield(); // return control immediately
88-
8987
while (!_cancellationToken.IsCancellationRequested)
9088
{
9189
try

src/MongoDB.Driver.Core/Core/Servers/ServerMonitor.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,14 @@ public void Initialize()
128128
{
129129
if (_state.TryChange(State.Initial, State.Open))
130130
{
131-
_ = MonitorServerAsync().ConfigureAwait(false);
131+
// the call to Task.Factory.StartNew is not normally recommended or necessary
132+
// we are using it temporarily to work around a race condition in some of our tests
133+
// the issue is that we set up some mocked async methods to return results immediately synchronously
134+
// which results in the MonitorServerAsync method making more progress synchronously than the test expected
135+
// by using Task.Factory.StartNew we introduce a short delay before the MonitorServerAsync Task starts executing
136+
// the delay is whatever time it takes for the new Task to be activated and scheduled
137+
// and the delay is usually long enough for the test to get past the race condition (though not guaranteed)
138+
_ = Task.Factory.StartNew(() => _ = MonitorServerAsync().ConfigureAwait(false)).ConfigureAwait(false);
132139
_ = _roundTripTimeMonitor.RunAsync().ConfigureAwait(false);
133140
}
134141
}
@@ -189,8 +196,6 @@ private async Task<IConnection> InitializeConnectionAsync(CancellationToken canc
189196

190197
private async Task MonitorServerAsync()
191198
{
192-
await Task.Yield(); // return control immediately
193-
194199
var metronome = new Metronome(_serverMonitorSettings.HeartbeatInterval);
195200
var monitorCancellationToken = _monitorCancellationTokenSource.Token;
196201

tests/MongoDB.Driver.Core.Tests/Core/Servers/HeartbeatDelayTests.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using System.Diagnostics;
1718
using System.Threading;
1819
using System.Threading.Tasks;
1920
using FluentAssertions;
@@ -38,13 +39,20 @@ public void Dispose_can_be_called_multiple_times()
3839
public void RequestHeartbeat_should_respect_to_minHeartbeatInterval([Values(10, -1)]int heartbeatIntervalInMinutes)
3940
{
4041
var heartbeatInterval = heartbeatIntervalInMinutes == -1 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMinutes(heartbeatIntervalInMinutes);
41-
var subject = new HeartbeatDelay(heartbeatInterval, TimeSpan.FromSeconds(2));
42+
var minHeartbeatInterval = TimeSpan.FromSeconds(2);
4243

44+
var stopwatch = Stopwatch.StartNew();
45+
var subject = new HeartbeatDelay(heartbeatInterval, minHeartbeatInterval);
4346
subject.RequestHeartbeat();
47+
var timeout = TimeSpan.FromMinutes(1);
48+
var result = Task.WaitAny(subject.Task, Task.Delay(timeout));
49+
if (result != 0)
50+
{
51+
throw new Exception($"The test timeout {timeout} is exceeded.");
52+
}
53+
stopwatch.Stop();
4454

45-
SpinWait.SpinUntil(() => subject.Task.Status != TaskStatus.WaitingForActivation, TimeSpan.FromMilliseconds(1500)).Should().BeFalse();
46-
Thread.Sleep(TimeSpan.FromMilliseconds(700));
47-
subject.Task.Status.Should().Be(TaskStatus.RanToCompletion);
55+
stopwatch.Elapsed.Should().BeGreaterOrEqualTo(minHeartbeatInterval - TimeSpan.FromMilliseconds(15));
4856
}
4957

5058
[Fact]

0 commit comments

Comments
 (0)