我试图通过创建新的 Windows 窗体应用程序并与 SQL Server 数据库(经典的NORTHWND database)通信来重现您所看到的内容。我有一个带有单个标签和三个按钮的表单 - 第一个按钮只是增加标签中显示的值,以便在表单响应或不响应时轻松测试。第二个按钮执行阻塞查询,第三个按钮执行异步查询。所有的代码都在下面..
当我单击“button2”时,GUI 像您描述的那样被冻结 - 单击 button1 不会增加标签中显示的数字。事实上,表单不会响应任何用户交互 - 在查询完成之前,试图拖动该表单是行不通的。
如果单击“button3”,则 GUI没有锁定(单击“button1”有效,拖动和调整表单大小仍然有效)。
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Windows.Forms;
using Dapper;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private int _counter = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_counter++;
label1.Text = _counter.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
using (var conn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;"))
{
var timer = new Stopwatch();
timer.Start();
label1.Text = "Starting..";
conn.Execute(@"
SELECT *
FROM Categories
INNER JOIN Customers
ON 1=1
INNER JOIN Employees
ON 1=1
");
timer.Stop();
label1.Text = "Done: " + timer.ElapsedMilliseconds + "ms";
}
}
private async void button3_Click(object sender, EventArgs e)
{
using (var conn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;"))
{
var timer = new Stopwatch();
timer.Start();
label1.Text = "Starting (async)..";
await conn.ExecuteAsync(@"
SELECT *
FROM Categories
INNER JOIN Customers
ON 1=1
INNER JOIN Employees
ON 1=1
");
timer.Stop();
label1.Text = "Done (async): " + timer.ElapsedMilliseconds + "ms";
}
}
}
}
我可以看到我的代码和你的代码之间的唯一区别是我将连接的打开保留给 ExecuteAsync 调用(因此我不需要使用 OpenAsync)并且我使用的是 SQL Server 而不是 Access (我在这里没有可在我的计算机上测试的访问权限)。
我尝试通过删除 conn 引用周围的“使用”、调用 OpenAsync、调用 ConfigureAwait 并在使用后显式关闭它,将我的代码更改为与您的更相似,但我无法重现该问题。我在有和没有 ConfigureAwait 的情况下都尝试过(因为在工作完成后将 false 传递给 this 会导致问题,因为 label1.Text 更新是从不允许的非 GUI 线程尝试的 - 将 true 传递给 ConfigureAwait 可以避免这个问题).. 但是我做不到。
如果您有可用的 SQL Server 实例,我建议您尝试针对 SQL Server 实例运行我的代码,以确保您正确使用 Dapper / async。然后尝试更改连接字符串(和 SQL 查询),以便它查询您的 Access 数据库并查看这是否是问题的原因(如果 Access is 能够在此中断异步,我会感到惊讶方式,但我不知道还有什么可能)。