2013-02-22 84 views
1

我有實現取消令牌的異步代碼。它的工作,但我不敢肯定,如果這是正確的方式做到這一點,所以我只是想反饋意見。C#5 Async等待.Task.Factory.Start新的取消

下面是實際的代碼:

/// <summary> 
    /// 
    /// </summary> 
    private async void SaveData() { 

     if (GetActiveServiceRequest() != null) 
     { 
      var tokenSource = new System.Threading.CancellationTokenSource(); 


      this.ShowWizardPleaseWait("Saving data..."); 

      var someTask = System.Threading.Tasks.Task<bool>.Factory.StartNew(() => 
      { 

       bool returnVal = false; 

       // Set sleep of 7 seconds to test the 5 seconds timeout. 
       System.Threading.Thread.Sleep(7000); 

       if (!tokenSource.IsCancellationRequested) 
       { 
        // if not cancelled then save data 

        App.Data.EmployeeWCF ws = new App.Data.EmployeeWCF(); 
        returnVal = ws.UpdateData(_employee.Data); 
        ws.Dispose(); 
       } 

       return returnVal; 

      }, tokenSource.Token); 


      if (await System.Threading.Tasks.Task.WhenAny(someTask, System.Threading.Tasks.Task.Delay(5000)) == someTask) 
      { 
       // Completed 
       this.HideWizardPleaseWait(); 
       if (someTask.Result) 
       { 
        this.DialogResult = System.Windows.Forms.DialogResult.OK; 
       } 
       else 
       { 
        this.DialogResult = System.Windows.Forms.DialogResult.Abort; 
       } 
       btnOK.Enabled = true; 
       this.Close(); 
      } 
      else 
      { 
       tokenSource.Cancel(); 

       // Timeout logic 
       this.HideWizardPleaseWait(); 
       MessageBox.Show("Timeout. Please try again.") 
      } 


     } 
    } 

是否異步/的await /解除代碼被很好的執行?

非常感謝並感謝您的反饋。

+0

太棒了!感謝您的提示 – VAAA 2013-02-22 15:37:33

回答

5

一般而言,您應該使用ThrowIfCancellationRequested。這將完成返回的Task處於取消狀態,而不是「成功運行到完成」狀態,結果爲false

其他景點:

  • 避免async void。這應該是async Task,除非它是一個事件處理程序。
  • Prefer Task.Run over TaskFactory.StartNew
  • 使用using
  • 如果您只是使用CancellationTokenSource作爲超時,那麼它具有特殊功能。不需要通過Task.DelayTask.WhenAny創建單獨的任務。

下面是更新後的代碼是什麼樣子:

private async Task SaveData() 
{ 
    if (GetActiveServiceRequest() != null) 
    { 
     var tokenSource = new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(5)); 
     var token = tokenSource.Token; 

     this.ShowWizardPleaseWait("Saving data..."); 

     var someTask = System.Threading.Tasks.Task.Run(() => 
     { 
      // Set sleep of 7 seconds to test the 5 seconds timeout. 
      System.Threading.Thread.Sleep(7000); 

      // if not cancelled then save data 
      token.ThrowIfCancellationRequested(); 
      using (App.Data.EmployeeWCF ws = new App.Data.EmployeeWCF()) 
      { 
       return ws.UpdateData(_employee.Data); 
      } 
     }, token); 

     try 
     { 
      var result = await someTask; 

      // Completed 
      this.HideWizardPleaseWait(); 
      if (result) 
      { 
       this.DialogResult = System.Windows.Forms.DialogResult.OK; 
      } 
      else 
      { 
       this.DialogResult = System.Windows.Forms.DialogResult.Abort; 
      } 
      btnOK.Enabled = true; 
      this.Close(); 
     } 
     catch (OperationCanceledException) 
     { 
      // Timeout logic 
      this.HideWizardPleaseWait(); 
      MessageBox.Show("Timeout. Please try again.") 
     } 
    } 
} 
+0

驚人的答覆!非常感謝您的幫助斯蒂芬......非常清楚,非常專業的答覆! – VAAA 2013-02-23 01:37:34

+0

當我調用SaveData()並將其懸停時,它說: 用法: await SaveData(); 警告: 因爲這個電話它沒有等待..... 這好嗎? – VAAA 2013-02-23 01:46:58

+0

可能不是。很可能,你應該「等待」它。 – 2013-02-23 02:38:55