dta*_*lor 5 c# asynchronous sqlcommand async-await
我已将我的应用程序精简到最小的 POC,但仍然得到相同的效果。看来 ExecuteScalarAsync 的行为类似于同步调用。我认为,当遇到等待时,异步方法中的其余代码将暂停,并且消息泵返回并从消息队列获取另一条消息,从而允许 UI 继续。当标量调用完成时,异步方法的剩余部分将被放回到消息队列中,以便它完成。
当这个小应用程序运行时,TestConnectionAsync 方法会挂起 UI,并且不会执行其他消息,直到 ExecuteScalarAsync 调用超时。
我做错了什么,还是这个异步方法的行为像同步方法?
该表单有两个按钮。第一个运行异步方法,第二个尝试使用令牌取消异步方法。我从来没有机会点击第二个按钮。
Form1.cs
public partial class Form1 : Form
{
private DB _db = new DB();
private string _nl = Environment.NewLine;
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "Starting" + _nl;
string resultString
= (string) await _db.TestConnectionAsync();
textBox1.AppendText(resultString + _nl);
textBox1.AppendText("Done" + _nl);
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.AppendText("Cancelling..." + _nl);
_db.CancelTest();
textBox1.AppendText("Submitted Cancel Token" + _nl);
}
}
Run Code Online (Sandbox Code Playgroud)
数据库cs
public class DB
{
private SqlCommand _command = null;
private CancellationTokenSource _tokenSource
= new CancellationTokenSource();
private CancellationToken _token;
public async Task<string> TestConnectionAsync()
{
_token = _tokenSource.Token;
string query = "SELECT COUNT(*) FROM tblDintData";
try
{
using (SqlConnection connection
= new SqlConnection(BuildConnectionString()))
{
connection.Open();
_command = new SqlCommand(query, connection);
await _command.ExecuteScalarAsync(_token);
return "Successful Database Connection";
}
}
catch (Exception ex)
{
return "Connection Failed:"
+ Environment.NewLine + ex.Message;
}
}
public void CancelTest()
{
_tokenSource.Cancel();
}
private string BuildConnectionString()
{
string ret = "";
ret = "Server=NotARealServer;"
+ "Database=NoSuchDatabase;"
+ "Trusted_Connection=True;";
return ret;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑 ***
好吧,我通过反复试验发现了一些东西。如果我还通过调用 Connection.OpenAsync 使 Connection.Open 异步,那么 UI 会突然变得响应灵敏。这并不直观,但这是我更改的行:
从:
connection.Open();
Run Code Online (Sandbox Code Playgroud)
到:
await connection.OpenAsync();
Run Code Online (Sandbox Code Playgroud)
但是,当我取消 CancellationTokenSource 时,ExecuteScalarAsync 仍然没有取消。有任何想法吗???
ExecuteScalarAsync确实是一个异步方法,但您的 UI 会停止,因为您没有异步调用这些方法。您可以在此 Microsoft 页面上了解如何更好地处理异步方法调用。
您还发现,您还需要异步打开连接。该链接包含打开连接、异步获取数据和取消查询的好示例。
编辑 ** 来自道格
是的,哈桑是对的。当问题一直出在 Open 上时,我一直沉迷于让 ExecuteScalarAsync 正常工作。根据经验,将来我将始终调用这样的命令:
await connection.OpenAsync(_token);
_command = new SqlCommand(query, connection);
await _command.ExecuteScalarAsync(_token);
Run Code Online (Sandbox Code Playgroud)
这样,如果出现连接问题,异步和取消行为仍然会起作用。
谢谢哈桑。