2013-06-28 27 views
6

Tôi có một nhiệm vụ mà tôi muốn hủy.Dừng một Tác vụ mà không cần ThrowIfCancellationRequested

Phương pháp thông thường để thực hiện việc này là với CancellationToken.

this.task = new SpecialTask(() => 
{ 
    for (int i = 0; i < ushort.MaxValue; i++) 
    { 
     CancelToken.ThrowIfCancellationRequested(); 
     Console.WriteLine(i); 
    } 
}, this.CancelToken); 

Tuy nhiên, trong thực tế mọi thứ không bao giờ đơn giản như vậy. đang async của chúng tôi không thể được looped và nó trông như thế này:

this.task = new SpecialTask(() => 
{ 
    CancelToken.ThrowIfCancellationRequested(); 
    Operation1(); 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation267(CancelToken); 

    CancelToken.ThrowIfCancellationRequested(); 
    object232.Operation345(); 

    CancelToken.ThrowIfCancellationRequested(); 
    object99.Operation44(CancelToken); 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation5(CancelToken); 

    ... 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation...n(CancelToken); 

}, this.CancelToken); 

tôi đã sử dụng số ngẫu nhiên cho các đối tượng và tên phương pháp để chứng minh rằng không có vòng lặp có thể được tạo ra bất cứ điều gì.

Điều phiền toái nhất là tôi phải tiếp tục viết lại CancelToken.ThrowIfCancellationRequested() cùng một lần.

Và, như thể điều đó là không đủ, tôi phải kéo CancellationToken trên toàn bộ mã của tôi chỉ để có thể dừng hoạt động dài - theo Microsoft - vào đúng thời điểm.

Có nói rằng, có cách nào tôi có thể phân phối các cuộc gọi lặp đi lặp lại đầu độc mã của tôi không?

Chúng tôi cũng biết rằng, khi sử dụng

try 
{ 
    task.Wait(cancelToken); 
} 
catch(OperationCancelledException) 
{ 
} 

một OperationCancelledException được ném và bắt đối với phương pháp Wait. Tuy nhiên, thao tác dài được thực thi bởi tác vụ không dừng lại nếu thỉnh thoảng không có CancelToken.ThrowIfCancellationRequested() kiểm tra.

Có cách nào có thể làm cho hoạt động bên trong dừng lại khi ngoại lệ bị phát hiện chờ đợi không?

+0

thể trùng lặp của [không đồng bộ hủy bỏ C Nhiệm vụ # TPL] (http://stackoverflow.com/questions/17321692/asynchronously-abort-c-sharp-tpl-tasks) – dtb

+1

Xem [Làm cách nào để hủy các hoạt động không đồng bộ không hủy được?] (http://blogs.msdn.com/b/pfxteam/archive/2012/10/05/ how-do-i-cancel-non-cancelable-async-operations.aspx) Tóm lại, bạn không biết. Bạn cần phải làm điều này, hoặc bạn không thể hủy bỏ nhiệm vụ. Điều đó nói rằng, bạn có thể làm một vài refactors để mã này để tránh một số sự lặp lại. – Servy

+0

Trong khi tôi hiểu sự cần thiết của việc đảm bảo hoạt động chạy dài được dừng lại vào đúng thời điểm, tôi đã hy vọng rằng khuôn khổ đó, ở mức thấp hơn, một số cơ chế sẵn có để hủy bỏ độc đáo. Tôi sẽ xem xét các liên kết bạn cung cấp càng sớm càng tốt, mặc dù. Cảm ơn! – Paul

Trả lời

2

Bạn có thể cấu trúc mã của bạn vào một vòng lặp để tránh việc hủy bỏ lặp đi lặp lại giữa mỗi dòng:

var actions = new List<Action>() 
{ 
    ()=>Operation1(), 
    ()=>Operation267(CancelToken), 
    ()=>object232.Operation345(), 
    //... 
}; 

foreach (var action in actions) 
{ 
    action(); 
    CancelToken.ThrowIfCancellationRequested(); 
} 
+0

Điều này đòi hỏi tôi phải tưởng tượng nhiều hạt mịn hơn để tách mã của tôi thành các phương pháp. Thay vì có 3 phương pháp vững chắc tốt, tôi gần như bị buộc phải chia thành nhiều phương pháp nhỏ hơn chỉ để việc hủy bỏ bị bắt sớm. Loại bỏ mã số hủy bỏ từ một nơi và thêm một địa điểm khác ở một nơi khác sẽ không làm – Paul

+1

@Paul Bạn vẫn có thể chuyển mã thông báo hủy vào các phương thức và thực hiện tương tự như vậy, vẫn cho phép mã tái cấu trúc thành các phương thức. – Servy

Các vấn đề liên quan