diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 8c859cecc3..ed2d274f5c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -284,7 +284,7 @@
-
+
@@ -317,7 +317,8 @@
-
+
+
@@ -756,6 +757,7 @@
+
True
True
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/ConcurrentQueueSemaphore.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/ConcurrentQueueSemaphore.NetStandard.cs
index d22b1b9c8c..45b801af51 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/ConcurrentQueueSemaphore.NetStandard.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/ConcurrentQueueSemaphore.NetStandard.cs
@@ -11,14 +11,22 @@ internal sealed partial class ConcurrentQueueSemaphore
{
public Task WaitAsync(CancellationToken cancellationToken)
{
- var tcs = new TaskCompletionSource();
- _queue.Enqueue(tcs);
- _semaphore.WaitAsync().ContinueWith(
- continuationAction: s_continuePop,
- state: _queue,
- cancellationToken: cancellationToken
- );
- return tcs.Task;
+ // try sync wait with 0 which will not block to see if we need to do an async wait
+ if (_semaphore.Wait(0, cancellationToken))
+ {
+ return Task.CompletedTask;
+ }
+ else
+ {
+ var tcs = new TaskCompletionSource();
+ _queue.Enqueue(tcs);
+ _semaphore.WaitAsync().ContinueWith(
+ continuationAction: s_continuePop,
+ state: _queue,
+ cancellationToken: cancellationToken
+ );
+ return tcs.Task;
+ }
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.Task.cs
similarity index 86%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetStandard.cs
rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.Task.cs
index 0a9ab39d7a..7ca2ee167e 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetStandard.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.Task.cs
@@ -2,14 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Net.Security;
-using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using System.Net.Sockets;
+
namespace Microsoft.Data.SqlClient.SNI
{
+ // NetCore2.1:
+ // DO NOT OVERRIDE ValueTask versions of ReadAsync and WriteAsync because the underlying SslStream implements them
+ // by calling the Task versions which are already overridden meaning that if a caller uses Task WriteAsync this would
+ // call ValueTask WriteAsync which then called TaskWriteAsync introducing a lock cycle and never return
+
internal sealed partial class SNISslStream
{
public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.ValueTask.cs
similarity index 98%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetCoreApp.cs
rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.ValueTask.cs
index 6a62e2b9ab..f4fa916d7c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.NetCoreApp.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.ValueTask.cs
@@ -2,16 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Net.Security;
-using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using System.Net.Sockets;
using System;
namespace Microsoft.Data.SqlClient.SNI
{
-
internal sealed partial class SNISslStream
{
public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)