SqlConnection.Open vs SqlConnection.OpenAsync – 这两者之间的区别是什么?

编辑:这归结为为什么只更改SqlConnection.Open()以等待异步代码中的SqlConnection.OpenAsync()导致强烈不同的行为。

除了明显的异步行为之外,异步代码中的同步代码中的SqlConnection.Open调用和等待SqlConnection.OpenAsync调用之间的区别是什么? 底层连接是否与数据库异步?

OpenAsync上的文档是精简版, https: //msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.openasync%28v=vs.110%29.aspx?f = 255 & MSPPError = -2147217396。

Open的异步版本,它使用ConnectionString指定的设置打开数据库连接。 此方法使用CancellationToken.None调用虚方法OpenAsync。(从DbConnectioninheritance。)

我觉得有趣的是,之前连接字符串中需要async = true,而在.net 4.5+中则不再需要它。 连接的行为有何不同?

https://msdn.microsoft.com/en-us/library/hh211418(v=vs.110).aspx

从.NET Framework 4.5开始,这些方法不再需要在连接字符串中使用Asynchronous Processing = true。

当我碰巧在异步应用程序中使用同步SqlConnection.Open并加载它时,我发现它执行得非常糟糕,早期运行连接池。 我希望打开连接是阻塞的,但是,在这些连接上执行异步命令(通过dapper)的行为有所不同。 那么,OpenAsync的做法有何不同?

编辑:

作为重现问题的请求代码(或者可能表现出差异)。 在执行大约180个并发异步命令时遇到运行此情况的Open()连接超时,使用OpenAsync()即使在超过300个并发命令时也不会遇到exception。 您可以推动并发以最终使其超时,但它肯定会更深入地执行并发命令。

using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Dapper; using Nito.AsyncEx; namespace AsyncSqlConnectionTest { class Program { public static int concurrent_counter = 0; public static int total_counter = 0; static void Main(string[] args) { var listToConsume = Enumerable.Range(1, 10000).ToList(); Parallel.ForEach(listToConsume, new ParallelOptions { }, value => { try { Task.Run(() => AsyncContext.Run(async () => { using (var conn = new SqlConnection("Data Source=.; Database=master; Trusted_Connection=True;")) { Interlocked.Increment(ref concurrent_counter); Interlocked.Increment(ref total_counter); await conn.OpenAsync(); var result = await conn.QueryAsync("select * from master..spt_values; waitfor delay '00:00:05'"); Console.WriteLine($"#{total_counter}, concurrent: {concurrent_counter}"); Interlocked.Decrement(ref concurrent_counter); } })).GetAwaiter().GetResult(); } catch (Exception e) { Console.Write(e.ToString()); } }); Console.ReadLine(); } } } 

编辑2:

这是一个只使用ADO.NET发现相同差异的测试。 值得注意的是Dapper的执行速度要快得多,但这不是重点。 同样,OpenAsync最终将获得超时,但是“更晚”并且永远不会是最大并行度为100(低于连接池大小)。

 using System; using System.Data.SqlClient; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsyncSqlConnectionTest { class Program { public static int concurrent_counter = 0; public static int total_counter = 0; static void Main(string[] args) { var listToConsume = Enumerable.Range(1, 10000).ToList(); Parallel.ForEach(listToConsume, new ParallelOptions { }, value => { try { Task.Run(async () => { using (var conn = new SqlConnection("Data Source=.; Database=master; Trusted_Connection=True;")) { Interlocked.Increment(ref concurrent_counter); Interlocked.Increment(ref total_counter); // this (no errors) await conn.OpenAsync(); // vs. this (timeouts) //conn.Open(); var cmd = new SqlCommand("select * from master..spt_values; waitfor delay '00:00:05'", conn); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { } } Console.WriteLine($"#{total_counter}, concurrent: {concurrent_counter}"); Interlocked.Decrement(ref concurrent_counter); } }).GetAwaiter().GetResult(); } catch (Exception e) { Console.Write(e.ToString()); } }); Console.ReadLine(); } } }