2012-11-13 25 views
9

Có thể bắt được khi bất kỳ Tác vụ nào chấm dứt ngoại lệ và đăng nhập không? Tôi đã thêm CurrentDomain_UnhandledException xử lý nhưng điều này không hữu ích.có thể bắt được khi bất kỳ Tác vụ nào chấm dứt ngoại lệ và đăng nhập không?

Tôi tạo các tác vụ bằng cách sử dụng Task.Factory.StartNew() như thường lệ. Khi một nơi nào đó bên trong ngoại lệ nhiệm vụ như vậy xảy ra nó treo âm thầm (nhưng nó phải làm việc mãi mãi, tôi cũng đang sử dụng tùy chọn LongRunning). Vì vậy, tôi muốn được thông báo về hành vi đó.

Lý tưởng nhất là tôi muốn đặt một số tùy chọn ở đâu đó để được thông báo khi bất kỳ Tác vụ trục trặc do ngoại lệ nào.

Nếu không thể, có thể tôi nên thêm thứ gì đó vào mỗi Tác vụ tôi tạo? Tất nhiên tôi chỉ có thể thêm khối lớn try{} finally{} bên trong mỗi Tác vụ, nhưng có lẽ có giải pháp tốt hơn?

Trả lời

2

Đối với các tác vụ mà bạn tự tạo cho mình, điều đó khá đơn giản: tạo các phương thức của riêng bạn gọi Task.Factory.StartNew(), nhưng sau đó cũng gọi Task.ContinueWith(loggingDelegate, TaskContinuationOptions.OnlyOnFaulted trước khi trả lại tác vụ.

Vấn đề là sẽ không thêm trình xử lý lỗi cho các tác vụ được tạo bởi các bit cơ sở hạ tầng khác - bao gồm các phương pháp không đồng bộ trong C# 5. Nó vẫn có thể hữu ích cho bạn.

Bạn cũng có thể sử dụng TaskScheduler.UnobservedTaskException, nhưng theo tên sẽ chỉ được gọi cho các trường hợp ngoại lệ chưa được quan sát bởi điều gì khác. (Một lần nữa, điều đó có thể tốt cho bạn ...)

+0

cảm ơn !. tôi tốt hơn như 'TaskScheduler.UnobservedTaskException'. Tôi tạo ra nhiều nhiệm vụ. Không ai trong số họ nên sụp đổ. Thay vì thêm "trình xử lý" vào mỗi tác vụ, tôi muốn thêm một trình xử lý "toàn cầu". – javapowered

+0

bạn có biết nếu tôi có thể in "tên tác vụ" hoặc thứ gì đó trong trình xử lý 'UnobservedTaskException'? bởi vì từ trường hợp ngoại lệ, không rõ nhiệm vụ cụ thể nào bị lỗi. – javapowered

+0

@javapowered: Tôi không biết bất cứ điều gì như thế, tôi sợ - nhưng tôi cho rằng ngoại lệ sẽ là một khởi đầu tốt. –

0

Quấn task.Wait() của bạn trong khối thử/nắm bắt và bắt AggregateException. Một cái gì đó như thế này -

Task<string[]> task1 = Task<string[]>.Factory.StartNew(() => GetAllFiles(path)); 

// Use this line to throw an exception that is not handled. 
try 
{ 
    task1.Wait(); 
} 
catch (AggregateException ae) 
{ 

    ae.Handle((x) => 
    { 
     if (x is UnauthorizedAccessException) // This we know how to handle. 
     { 
      Console.WriteLine("You do not have permission to access all folders 
           in this path."); 
      Console.WriteLine("See your network administrator or try 
           another path."); 
      return true; 
     } 
     return false; // Let anything else stop the application. 
    }); 
} 

Chi tiết có thể tìm thấy tại đây - Handle exceptions thrown by Task.

2

Bạn có thể sử dụng một phương pháp tiện ích mở rộng thực hiện một thao tác khi một ngoại lệ đã được làm mờ. Điều này xảy ra khi Tác vụ bị lỗi. Vì vậy, nếu nó có một nhiệm vụ khác để tiếp tục, phần tiếp theo có thể kiểm tra xem tác vụ trước đó có bị lỗi hay không và ghi lại ngoại lệ.

Tôi thường sử dụng phương pháp này:

//If you want to chain more tasks.. 
public static Task<T> Continue<T>(this Task<T> task, Action<T> action) 
{ 
    if (!task.IsFaulted) 
    { 
     task.ContinueWith((t) => action(t.Result), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion); 
    } 
    return task; 
} 

public static Task OnException(this Task task, Action<Exception> onFaulted) 
{ 
    task.ContinueWith(c => 
    { 
     var excetion = c.Exception; 
      onFaulted(excetion); 
    }, 
     TaskContinuationOptions.OnlyOnFaulted | 
     TaskContinuationOptions.ExecuteSynchronously); 
    return task; 
} 

Vì vậy, bạn có thể sử dụng:

Task.Factory.StartNew(...).OnException(ex => Log(ex)); 

Hy vọng nó giúp.

6

Giả sử bạn có một Test như Task để chạy:

static int Test() 
{ 
    throw new Exception(); 
} 
  1. Đầu tiên tiếp cận - Process ngoại lệ trong chủ đề của người gọi:

    Task<int> task = new Task<int>(Test); 
    task.Start(); 
    
    try 
    { 
        task.Wait(); 
    } 
    catch (AggregateException ex) 
    { 
        Console.WriteLine(ex); 
    } 
    

    Lưu ý: Trường hợp ngoại lệ sẽ được gõ AggregateException. Tất cả các ngoại lệ thực tế có sẵn thông qua tài sản ex.InnerExceptions.

  2. Thứ hai cách tiếp cận - Process ngoại lệ trong chủ đề của một số nhiệm vụ:

    Xác định ExceptionHandler theo cách này:

    static void ExceptionHandler(Task<int> task) 
    { 
        var ex = task.Exception; 
        Console.WriteLine(ex); 
    } 
    

    Cách sử dụng:

    Task<int> task = new Task<int>(Test); 
    task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted); 
    task.Start(); 
    

tham khảo: How to: Handle Exceptions Thrown by Tasks

+0

đánh dấu câu trả lời của Jon là nguyên nhân chính xác mà anh ta đề xuất sử dụng UnobservedTaskException – javapowered

0

Bạn có thể tạo một tiếp tục OnlyOnFaulted trên Công việc của bạn mà quan sát ngoại lệ và nhật ký/báo cáo sự cố.

t.ContinueWith(task => 
{ 
    // Report and log error 
}, System.Threading.CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext()); 

Mã trên sẽ chạy tác vụ trên chuỗi giao diện người dùng vì TaskScheduler.FromCurrentSynchronizationContext(). Điều này có thể cần thiết nếu bạn đang sử dụng winforms và cần thông báo cho người dùng.

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