2016-12-11 51 views
0

我无法取消异步/等待呼叫取消按钮单击。如果要在网格中加载数据需要很长时间,我想取消查询。我是新来的使用异步/等待方法,并提到了很多例子,但无法锻炼如果。请认真看看我的下面的代码和请帮助。谢谢无法取消异步/等待呼叫按钮单击

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;[email protected]"; 
       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(); 
     } 



    } 
} 
+2

所以会发生什么,当你运行该代码?你有什么例外吗?你提供的细节越多,你的问题就越有可能得到回答。 –

+0

嗨Ruben,不,它不会抛出任何错误,只是完成查询并将数据加载到网格视图而没有接受取消请求。我不知道如何调试它并排除故障。 –

回答

-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); 
+0

我发现这个解决方案不是别的,而是Stackoverflow,这是让你的查询得到回答的好地方。 :) http://stackoverflow.com/questions/39166619/will-this-cancel-an-executereaderasync –

0

的问题是这行代码:

await Task.Run(() => dt.Load(reader), cts.Token); 

相反,你可以期待什么,传给Task.RunCancellationToken只取消了开始该任务的,而不是任务本身。换句话说,一旦Load已经启动,它不能被取消。

理想情况下,您应该在现代代码中使用除DataTable之外的其他东西;其他数据库API已更新以支持取消。如果这是不可能的,那么你可以使用CancellationTokenRegistration作为你的答案。然而,你应该使用Result - 使用await代替:

using (CancellationTokenRegistration ctr = cts.Token.Register(() => cmd.Cancel())) 
using (var reader = await cmd.ExecuteReaderAsync(cts.Token)) 
    dt.Load(reader);