我无法在取消按钮点击时取消async / await调用。如果在网格中加载数据需要很长时间,我想取消查询。我是新手使用async / await方法并参考了很多例子,但是如果不能锻炼。请看下面的代码,请帮忙。感谢
namespace MyFirstAsync
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
CancellationTokenSource cts ;
private async void btnExecute_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
try
{
string connectionString = "Data Source=G50-80;Initial Catalog=HPSF_Compdb;User ID=sa;Password=sql@2012";
string sqlQuery = "select top 900000 * from requestevent.result";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sqlQuery, conn);
await conn.OpenAsync(cts.Token);
SqlDataReader reader = await cmd.ExecuteReaderAsync(cts.Token);
DataTable dt = new DataTable();
//cts.Cancel();
await Task.Run(() => dt.Load(reader), cts.Token);
gvData.Invoke(new gvDelegate(UpdateDataToGrid), new object[] { dt });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public delegate void gvDelegate(DataTable dt);
public void UpdateDataToGrid(DataTable dt)
{
gvData.DataSource = dt;
}
private void btncancel_Click(object sender, EventArgs e)
{
cts.Cancel();
}
}
}
答案 0 :(得分:0)
问题在于这行代码:
await Task.Run(() => dt.Load(reader), cts.Token);
与您的期望相反,传递给CancellationToken
的{{1}}仅取消该任务的开始,而不取消任务本身。换句话说,一旦Task.Run
开始,就无法取消。
理想情况下,您应该在现代代码中使用Load
以外的其他内容;其他数据库API已更新,以支持取消。如果无法做到这一点,那么您可以在答案中使用DataTable
。但是,您应该不使用CancellationTokenRegistration
- 改为使用Result
:
await
答案 1 :(得分:-1)
我找到了上述问题的解决方案,只是改变了数据加载到数据表的方式。请使用新代码替换已注释的旧代码,并且按预期工作正常。新代码我只是复制和粘贴,但我仍然不知道如何描述新代码的工作方式,因为我是新手。但这对我有用。如果您区分两者,请解释一下。
using (CancellationTokenRegistration ctr = cts.Token.Register(() => cmd.Cancel()))
{
using (var reader = cmd.ExecuteReaderAsync(cts.Token))
{
dt.Load(reader.Result);
}
}
//SqlDataReader reader = await cmd.ExecuteReaderAsync(cts.Token);
//DataTable dt = new DataTable();
//await Task.Run(() => dt.Load(reader), cts.Token);