26

Tôi đã chơi vòng với async ctp sáng nay và có một chương trình đơn giản với buttonlabel. Nhấp vào button và bắt đầu cập nhật label, dừng button nó dừng ghi vào label. Tuy nhiên, tôi không chắc chắn làm thế nào để thiết lập lại các CancellationTokenSource để tôi có thể khởi động lại quá trình. Mã của tôi là dưới đây:Làm cách nào để đặt lại CancellationToken đúng cách?

public partial class MainWindow : Window 
{ 
    CancellationTokenSource cts = new CancellationTokenSource(); 
    public MainWindow() 
    { 
     InitializeComponent(); 
     button.Content = "Start"; 
    } 

    async Task DoWork(CancellationToken cancelToken) 
    { 
     int i = 0; 
     while (!cancelToken.IsCancellationRequested) 
     { 
      label.Content = i++.ToString(); 
      await TaskEx.Delay(50, cancelToken); 
     } 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (button.Content == "Start") 
     { 
      button.Content = "Stop"; 
      DoWork(cts.Token); 
     } 
     else 
     { 
      button.Content = "Start"; 
      cts.Cancel(); 
     } 
    } 
} 
+0

Có phải C# 5.0 không? Nó không biên dịch trong .NET 4.0 – Fulproof

+0

bạn vẫn có thể nhận được ctp cho 4.0. Tuy nhiên, có, đây là một tính năng 4.5 – poco

Trả lời

51

Bạn cần phải tạo lại CancellationTokenSource - không có cách nào để "thiết lập lại" này một khi bạn cài đặt nó.

Điều này có thể đơn giản như:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if (button.Content == "Start") 
    { 
     button.Content = "Stop"; 
     cts.Dispose(); // Clean up old token source.... 
     cts = new CancellationTokenSource(); // "Reset" the cancellation token source... 
     DoWork(cts.Token); 
    } 
    else 
    { 
     button.Content = "Start"; 
     cts.Cancel(); 
    } 
} 
+1

Khi nào bạn phải vứt bỏ nó khi đóng ứng dụng? Khi bạn phải đợi trước khi Thread được thực hiện, bạn sẽ nhận được ngoại lệ ObjectDisposed. – Zerowalker

+0

@ user2587718 Nó thực sự phụ thuộc vào loại đối tượng, vv Tôi muốn khuyên bạn nên hỏi câu hỏi của riêng bạn về việc này. –

2

Thậm chí, tôi đã có cùng một vấn đề và tôi figured it out rằng, cách tốt nhất để giải quyết nó là tạo ra hủy nguồn thẻ mới ngay trước khi gọi phương pháp này.

đây là những gì tôi làm trên nút bắt đầu của tôi nhấp chuột:

cancellationTokenSource = new CancellationTokenSource(); 
cancellationToken = cancellationTokenSource.Token; 
Task.Factory.StartNew(StartUpload, cancellationToken); 

tôi thay đổi chú thích cho cùng một nút để hủy bỏ và khi một nhấp chuột xảy ra trên hủy, tôi gọi

cancellationTokenSource.Cancel(); 

đây là mã đầy đủ:

if (button3.Text != "&Start Upload") 
     { 
      cancellationTokenSource.Cancel(); 
     } 
     else 
     { 
      try 
      { 
       cancellationTokenSource = new CancellationTokenSource(); 
       cancellationToken = cancellationTokenSource.Token; 
       Task.Factory.StartNew(StartUpload, cancellationToken); 
      } 
      catch (AggregateException ex) 
      { 
       var builder = new StringBuilder(); 
       foreach (var v in ex.InnerExceptions) 
        builder.Append("\r\n" + v.InnerException); 
       MessageBox.Show("There was an exception:\r\n" + builder.ToString()); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 
Các vấn đề liên quan