2013-04-04 36 views
9

Hãy xem xét mã sau sử dụng chức năng thư viện Task cơ bản với một CancellationTokenSource. Nó khởi động một chuỗi điền vào một từ điển với giá và đọc dữ liệu từ một db máy chủ SQL. Chủ đề kết thúc sau khoảng 10 phút và cứ sau 2 giờ nó lại được khởi động lại, hãy gọi Hủy trước trong trường hợp chủ đề vẫn đang chạy.Ngoại lệ khi chạy System.Threading.Tasks.Task

private CancellationTokenSource mTokenSource = new CancellationTokenSource(); 

internal Prices(Dictionary<string, Dealer> dealers) 
{ 
    mDealers = dealers; 
    mTask = Task.Factory.StartNew 
      (() => ReadPrices(mTokenSource.Token), mTokenSource.Token); 
} 

internal void Cancel() 
{ 
    mTokenSource.Cancel(); 
} 
private void ReadPrices(CancellationToken ct) 
{ 
    using (SqlConnection connection = 
      new SqlConnection(ConfigurationManager.AppSettings["DB"])) 
    { 
     connection.Open(); 
     var dealerIds = from dealer in mDealers.Values 
         where dealer.Id != null 
         select dealer.Id; 
     foreach (var dealerId in dealerIds) 
     { 
      if (!ct.IsCancellationRequested) 
      { 
       FillPrices(connection); 
      } 
      else 
       break; 
     } 
    } 
} 

Hiện tại, ứng dụng gặp sự cố ngoại lệ sau trong nhật ký sự kiện.

Ứng dụng: Engine.exe Framework Phiên bản: v4.0.30319 Mô tả: Quá trình bị chấm dứt do một ngoại lệ chưa được giải quyết. Thông tin ngoại lệ: System.AggregateException Stack: tại System.Threading.Tasks.TaskExceptionHolder.Finalize()

Nó phải có để làm với mã ở đây vì thư viện Nhiệm vụ không được sử dụng bất cứ nơi nào khác nhưng tôi không thể tìm ra điều gì sai với mã. Có ai có một ý tưởng những gì có thể sai ở đây?

+4

Thật không may, bạn không chụp đủ nhật ký của mình. 'AggregateException' có thể chứa bất kỳ số ngoại lệ nào khác và đó là những ngoại lệ có nhiều khả năng chứa thông tin hữu ích hơn để hỗ trợ chẩn đoán sự cố. –

+0

Ngoài ra "Chủ đề kết thúc sau khoảng 10 phút và cứ sau 2 giờ ... trong trường hợp chủ đề vẫn đang chạy." - Nghe có vẻ như bạn đang xem xét vấn đề mà bạn nên điều tra - thường mất 10 phút, nhưng đôi khi vẫn chạy sau 2 giờ ... –

+0

có chương trình khách hàng có thể hủy chuỗi bất kỳ lúc nào và khởi động lại vì vậy việc hủy bỏ chắc chắn là cần thiết – Laurijssen

Trả lời

19

Công việc muốn cảm thấy được lắng nghe. Nghe có vẻ như không có gì vui. Bạn không nhận được một "cơ hội cuối cùng" để nghe nó ra, mặc dù:

TaskScheduler.UnobservedTaskException += (sender, args) => 
{ 
    foreach (var ex in args.Exception.InnerExceptions) 
    { 
     Log(ex); 
    }    
    args.SetObserved(); 
}; 

Chú giải này không có ý định như sửa chữa - nó được thiết kế để cho phép bạn xem những gì Task đang bùng nổ và với những gì lỗi. Các SetObserved() sẽ ngăn chặn nó giết chết ứng dụng của bạn. Nhưng sửa chữa đây là lý tưởng:

  • đừng để công việc của bạn ném,
  • hoặc chắc chắn rằng bạn đang có để kiểm tra tình trạng của các nhiệm vụ sau

Đó là khá có thể không hài lòng với việc phát hiện hủy của bạn. IIRC cách ưa thích để làm điều đó sẽ là:

foreach(...) { 
    if(ct.IsCancellationRequested) { 
     // any cleanup etc 
     ct.ThrowIfCancellationRequested(); 
    } 
    ... 
} 

hoặc đơn giản hơn nếu không dọn dẹp là cần thiết, chỉ cần:

foreach(...) { 
    ct.ThrowIfCancellationRequested(); 
    ... 
} 

Tương tự, nó có thể chỉ là một ngoại lệ truy cập dữ liệu. Có bất kỳ số nào ngoại lệ có thể xảy ra khi nói chuyện với cơ sở dữ liệu. Thời gian chờ, bế tắc, không thể kết nối, v.v.

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