I'm trying to open a connection to an SQL server asynchronously, so as not to tie up the UI thread. But I've found that the call to connection.OpenAsync()
does not return until the connection has been opened, exactly as with connection.Open()
.
This code reproduces the issue:
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");
}
In this case, 192.168.1.254
is non-existent. The message about to connect
appears immediately, but then while waiting for the connection to time out nothing happens, then after the connection times out the messages started
and done
appear at the same time. I would expect that the message started
would appear immediately after the message about to connect
, then the message done
would appear later once the connection has timed out.
I'm guessing that I'm doing something wrong with the returned Task
, but the Microsoft page on Task-based Asynchronous Pattern certainly implies that I should simply be able to call the OpenAsync()
method and the returned Task
will be running asynchronously, instead of the operation taking place synchronously and tying up the calling thread until the Task
completes.
async
isn't concurrent, it'll run synchronously until something gives control back after registering with something like an IO completion port.DbConnection
.