【发布时间】:2025-12-12 04:35:02
【问题描述】:
我正在尝试异步打开与 SQL 服务器的连接,以免占用 UI 线程。但是我发现在打开连接之前,对connection.OpenAsync() 的调用不会返回,与connection.Open() 完全一样。
这段代码重现了这个问题:
public static void Main(string[] args)
{
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder.UserID = "sa";
builder.Password = "1234";
builder.DataSource = "192.168.1.254\\SQLEXPRESS";
builder.InitialCatalog = "MyDatabase";
builder.PersistSecurityInfo = true;
DbConnection connection = new System.Data.SqlClient.SqlConnection(builder.ConnectionString);
Console.WriteLine("about to connect");
Task connection_task = connection.OpenAsync();
Console.WriteLine("started");
while (!connection_task.IsCompleted && !connection_task.IsFaulted && !connection_task.IsCanceled)
{
Console.WriteLine("busy");
}
Console.WriteLine("done");
}
在这种情况下,192.168.1.254 不存在。消息about to connect 立即出现,但是在等待连接超时时没有任何反应,然后在连接超时后消息started 和done 同时出现。我希望消息started 会在消息about to connect 之后立即出现,然后消息done 会在连接超时后出现。
我猜我对返回的 Task 做错了,但Task-based Asynchronous Pattern 上的 Microsoft 页面肯定暗示我应该能够简单地调用 OpenAsync() 方法和返回的 Task将异步运行,而不是同步进行操作并占用调用线程直到 Task 完成。
【问题讨论】:
-
我完全尝试了这段代码,它的行为符合预期,在“完成”之前我得到了“忙碌”的负载。这是 VS 2017 中针对 .NET 4.6.1 的新控制台应用程序。
-
我的目标是 MonoDevelop 中的 .NET 4.5。我在 Windows 10 和 Linux 上遇到了相同的行为。
-
我也得到了和亚当一样的结果,它打印了很多次“忙碌”,然后“完成”。
-
@Michael 好的,所以我们已经有所不同了。对我来说,这似乎是 Mono 中的一个错误,当它遇到可以注册某种等待的位置时,它不会产生任务。
async不是并发的,它会同步运行,直到在向 IO 完成端口之类的东西注册后给予控制权。 -
@AndyJ 不是语法错误,ADO.NET 连接源自
DbConnection。
标签: c# multithreading asynchronous sqlconnection