2009-08-30 9 views
6

Eşzamansız programlamamda (beginInvoke/endInvoke) bir istisna işleme yaklaşımına sahip olmak istiyorum; burada herhangi bir iş parçacığı (beginInvoke) başarısız olursa, tüm diğer uyumsuz işlem işleyicilerinin çalışmayı durdurmasını istiyorum. Ben de örnek kod ekliyorum aşağıda ?, bazı çözüm önermek edin:Asenkron Multithreading İstisnası İşleme?

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, genel olarak kabul edilen asenkronize kısaltma Async değil, Asynch değil :) –

cevap

2

iyi yolu ortak ManualResetEvent kullanmak muhtemelen. Örneğin

:

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(); 
     } 
    } 
} 

burada ilginç bölüm WaitOne (0, true) için çağrıdır. 0 zaman aşımı kullanırsanız, iplik engellenmez. ManualResetEvent, işletim sistemi tarafından senkronize edildiğinden, bu özel yöntem çağrısı, yarış koşulları hakkında endişelenmenize gerek kalmadan bir sinyali kontrol etmenin veya kendi kilitlemenizi gerçekleştirmenin kolay bir yoludur.

+1

Uçucu boole da bir sonlandırma bayrağı olarak çalışmaz mı? – Amnon

+0

Teoride evet. Bazı durumlarda, hatta daha hızlı olabilir. Ancak * volatile * anahtar kelimesi çok fazla yan etkiye sahiptir - aslında sadece değişkenin kendisi değil, değişkene erişen her blok için kodun oluşturulma şeklini değiştirir. Performans önemli bir sorun olmadığı sürece genellikle kilitleri ve senkro ilkelleri * uçucu * alanlara tercih ederim. – Aaronaught