2017-02-13 26 views
3

考慮,2個按鈕的表單和一個RichTextBox:與Task.Run有什麼區別,void方法和Task方法返回null?

public partial class MainForm : Form 
{ 
    CancellationTokenSource cts; 
    CancellationToken token; 

    public MainForm() 
    { 
     InitializeComponent(); 
    } 

    private void MainForm_Load(object sender, EventArgs e) 
    { 
     cts = new CancellationTokenSource(); 
     token = cts.Token; 
     var task = Task.Run(() => WriteSomeLines(), token); 
    } 

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     cts.Dispose(); 
    } 

    private void btnStart_Click(object sender, EventArgs e) 
    { 
     cts = new CancellationTokenSource(); 
     token = cts.Token; 
     var task = Task.Run(() => WriteSomeLines(), token); 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      cts.Cancel(); 
      cts.Dispose(); 
     } 
     catch (ObjectDisposedException exc) 
     { 
      MessageBox.Show(exc.GetType().Name); 
      //object disposed 
     } 
    } 

    public void WriteSomeLines() 
    { 
     if (ControlInvokeRequired(rtbLoops,() => rtbLoops.Text += "Starting new loop \r\n")) ; 
     else rtbLoops.Text += "Starting new loop \r\n"; 
     for (int i = 0; i < 30; i++) 
     { 
      try 
      { 
       if (ControlInvokeRequired(rtbLoops,() => { rtbLoops.AppendText("New line " + i + "\r\n"); rtbLoops.ScrollToCaret(); })) ; 
       else rtbLoops.AppendText("New line " + i + "\r\n"); 

       Thread.Sleep(250); 
       token.ThrowIfCancellationRequested(); 
      } 
      catch (OperationCanceledException ae) 
      { 
       MessageBox.Show(ae.GetType().Name); 
       return; 
      } 
     } 
     return; 
    } 

    public bool ControlInvokeRequired(Control c, Action a) 
    { 
     if (c.InvokeRequired) 
      c.Invoke(new MethodInvoker(delegate { a(); })); 
     else 
      return false; 

     return true; 
    }  
} 

是否有區別,如果WriteSomeLines()是返回void我用回裏面,或者如果WriteSomeLines()返回的任務,我也返回null呢?我看,我不能空回來方法使用await,但是任務宣佈後插入

await task; 

(在上面的代碼)編譯完全正常,並沒有問題運行。

編輯:

private async void btnStart_Click(object sender, EventArgs e) 
    { 
     cts = new CancellationTokenSource(); 
     token = cts.Token; 
     var task = Task.Run(() => WriteSomeLines(), token); 
     await task; 
     rtbLoops.Text += "Task complete"; 
    } 

這將編譯沒有問題,如果WriteSomeLines()返回void。

此外,稍微未實現,我在這裏正確地處置CancellationTokenSource

第二個編輯:

因此,這是正確的做法:

private async void btnStart_Click(object sender, EventArgs e) 
    { 
     cts.Dispose(); 
     cts = new CancellationTokenSource(); 
     token = cts.Token; 
     var task = Task.Run(() => WriteSomeLines(), token); 
     bool result = await task; 
     if(result == true) rtbLoops.Text += "Task complete \r\n"; 
    } 

public async Task<bool> WriteSomeLines() 
    { 
     if (ControlInvokeRequired(rtbLoops,() => rtbLoops.Text += "Starting new loop \r\n")) ; 
     else rtbLoops.Text += "Starting new loop \r\n"; 
     for (int i = 0; i < 30; i++) 
     { 
      try 
      { 
       if (ControlInvokeRequired(rtbLoops,() => { rtbLoops.AppendText("New line " + i + "\r\n"); rtbLoops.ScrollToCaret(); })) ; 
       else rtbLoops.AppendText("New line " + i + "\r\n"); 
       await Task.Delay(250); 
       token.ThrowIfCancellationRequested(); 
      } 
      catch (OperationCanceledException ae) 
      { 
       MessageBox.Show(ae.GetType().Name); 
       return false; 
      } 
     } 
     return true; 

回答

4

你不應該返回一個空任務;這應該會導致運行時NullReferenceException錯誤。

可以內的async void方法使用await,但await消耗async void方法不能使用(因爲你不能awaitvoid)。

我建議您查看我的async intro blog post;它應該有助於您更好地瞭解asyncawait

我在這裏正確處理CancellationTokenSource?

您的開始按鈕需要在創建新的按鈕時取消/配置舊的cts

相關問題