2009-08-30 31 views
6

Tôi muốn có một cách tiếp cận xử lý ngoại lệ trong lập trình không đồng bộ của tôi (beginInvoke/endInvoke) trong đó nếu bất kỳ một luồng nào (beginInvoke) không thành công, thì tôi muốn tất cả luồng xử lý asynchrounous khác ngừng hoạt động. Xin gợi ý một số giải pháp dưới đây ?, Tôi gắn mẫu mã của tôi cũng:Xử lý ngoại lệ đa luồng không đồng bộ?

public List<ThreadResultDto> SendMailAsynch(List<ThreadRequestDto> requestDto) 
{ 
    List<ThreadResultDto> resultDto = new List<ThreadResultDto>(); 
    List<IAsyncResult> asyncResults = new List<IAsyncResult>(); 

    foreach (ThreadRequestDto t in requestDto) 
    { 
     //Create a delegate. 
     DoSomeAsynchWorkDelegate del = new DoSomeAsynchWorkDelegate(DoSomeAsynchWork); 
     // Initiate the asynchronous call 
     IAsyncResult a = del.BeginInvoke(t,null, del); 
     //IAsyncResult a = del.BeginInvoke(t, null,null); 
     asyncResults.Add(a); 
    } 

    foreach (IAsyncResult ar in asyncResults) 
    { 
     // wait for each one to complete, then call EndInvoke, passing in the IAsyncResult. 
     // We cast ar.AsyncState to a DoSomeAsynchWorkDelegate, as we passed it in as the second parameter to BeginInvoke. 
     ar.AsyncWaitHandle.WaitOne(); 

     //AsyncState property of IAsyncResult is used to get the delegate that was used to call that method 
     DoSomeAsynchWorkDelegate del = (DoSomeAsynchWorkDelegate)ar.AsyncState; 

     // Call EndInvoke to get the result. Add the result to the list of items. 
     resultDto.Add(del.EndInvoke(ar)); 
    } 

    return resultDto; 
} 
+1

FYI, chữ viết tắt được chấp nhận chung của không đồng bộ là Async, không phải Asynch :) –

Trả lời

2

Cách tốt nhất có lẽ là sử dụng một chia sẻ ManualResetEvent.

Ví dụ:

class MyClass 
{ 
    private ManualResetEvent workFailedEvent = new ManualResetEvent(false); 

    public List<ThreadResultDto> SendMailAsynch(List<ThreadRequestDto> requestDto) 
    { 
     workFailedEvent.Reset(); 

     // --- The rest of your code as written in your post --- 
    } 

    private void DoAsyncWorkFirst() 
    { 
     try 
     { 
      for (int i = 0; i < 10000; i++) 
      { 
       if (workFailedEvent.WaitOne(0, true)) 
       { 
        break; 
       } 

       // -- Do some work here --- 
      } 
     } 
     catch (MyException) 
     { 
      workFailedEvent.Set(); 
     } 
    } 

    private void DoAsyncWorkSecond() 
    { 
     try 
     { 
      for (int j = 0; j < 20000; j++) 
      { 
       if (workFailedEvent.WaitOne(0, true)) 
       { 
        break; 
       } 
       // --- Do some different work here --- 
      } 
     } 
     catch (MyOtherException) 
     { 
      workFailedEvent.Set(); 
     } 
    } 
} 

Phần thú vị ở đây là cuộc gọi đến WaitOne (0, true). Nếu bạn sử dụng hết thời gian chờ 0 thì chuỗi sẽ không chặn. Kể từ khi ManualResetEvent được đồng bộ hóa bởi hệ điều hành, cuộc gọi phương thức cụ thể này là một cách thuận tiện để kiểm tra tín hiệu mà không phải lo lắng về điều kiện chủng tộc hoặc thực hiện khóa của riêng bạn.

+1

Sẽ không phải là một bool dễ bay hơi cũng hoạt động như một lá cờ chấm dứt? – Amnon

+0

Về lý thuyết có. Trong một số trường hợp, nó thậm chí có thể nhanh hơn. Nhưng từ khóa * dễ bay hơi * có rất nhiều tác dụng phụ - nó thực sự thay đổi cách mã được tạo ra cho mỗi khối truy cập biến, không chỉ là biến. Tôi thường thích khóa và synchro nguyên thủy để * dễ bay hơi * lĩnh vực trừ khi hiệu suất là một vấn đề lớn. – Aaronaught