2016-12-11 79 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);