我正在阅读 documentation for DbConnection.OpenAsync(CancellationToken)
并找到以下代码段:
The default implementation invokes the synchronous Open call and returns a completed task. The default implementation will return a cancelled task if passed an already cancelled cancellationToken. Exceptions thrown by Open will be communicated via the returned Task Exception property.
现在,如果我的网络连接不稳定/速度慢,并且使用的数据库提供程序没有覆盖 DbConnection.OpenAsync(CancellationToken)
(即,我使用的不是 System.Data.SqlClient
),和如果我将其放入 UI Button 的事件处理程序中,例如:(假设代码,未经测试)
async void button1_Clicked(object sender, EventArgs e)
{
using (var connection = MyProviderFactory.CreateConnection())
{
button1.Text = "Opening…";
connection.ConnectionString = _SomeString;
try
{
await connection.OpenAsync(default);
button1.Text = "Opened successfully!";
}
catch (Exception ex)
{
button1.Text = ex.Message;
}
}
}
根据我引用的文档,如果连接需要足够长的时间才能完成,如果提供者没有覆盖默认实现,我的表单将在建立连接时显示为“(未响应)”。无论底层数据库提供程序如何,为了防止这种情况发生,我不妨执行 await Task.Run(async () => await connection.OpenAsync());
。为什么默认实现是这样的?在不编写提供程序感知代码的情况下,如何知道何时需要 Task.Run()
?
最佳答案
您的 await Task.Run(async () => await connection.OpenAsync())
不会在同一个线程中执行 connection.OpenAsync()
,但是connection.OpenAsync()
和 connection.Open()
依赖线程本地状态是完全合理的。他们可能而且通常应该注意 Transaction.Current
, 例如。如果 .NET Framework 在后台线程中静默执行 connection.Open()
,有些人会得到非常错误的结果。
关于c# - 为什么 DbConnection.OpenAsync(CancellationToken) 的默认实现是同步的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34911914/