2011-09-29 8 views
2

작업 내에서 병렬 루프 (Parallel.ForEach 및/또는 Parallel.For)에 의해 발생한 예외를 처리하는 좋은 방법이라고 생각하는지 알고 싶습니다.작업 및 병렬 루프의 예외 처리. (Threading - TPL)

나는 그렇게 나쁘지 않다고 생각하지만, 내 의견은 유용 할 수 있습니다! 당신이 내게 어떤 빛을 던질 수 있기를 바랍니다!

(나는 물론, 프레임 워크 4.0을 VS2010를 사용)

class Program 
{ 
    private static ConcurrentQueue<Exception> _exceptions = new ConcurrentQueue<Exception>(); 
    private static readonly ExceptionManager _exceptionManager = new ExceptionManager(); 

    static void Main() 
    { 
     var process = new SomeProcess(_exceptions); 
     var otherProcess = new SomeOtherProcess(_exceptions); 

     var someProcess = new Task(() => 
             { 
              process.InitSomeProcess(); 
              process.DoSomeProcess(); 
             }); 

     var someOtherProcess = new Task(() => 
              { 
               otherProcess.InitSomeOtherProcess(); 
               otherProcess.DoSomeOtherProcess(); 
              }); 
     someProcess.Start(); 
     someOtherProcess.Start(); 

     try 
     { 
      someProcess.Wait(); 
      someOtherProcess.Wait(); 
     } 
     catch (Exception ex) 
     { 
      _exceptionManager.Manage(ex); 
     } 
     finally 
     { 
      Console.WriteLine(); 

      foreach (var exception in _exceptions) 
      { 
       _exceptionManager.Manage(exception); 
      } 
      _exceptions = new ConcurrentQueue<Exception>(); //Delete exceptiones to prevent manage them twice (maybe this could be one in a more elegant way). 
     } 
     Console.ReadKey(); 
    } 
} 

public class ExceptionManager 
{ 
    public void Manage(Exception ex) 
    { 
     Console.WriteLine("Se dió una {0}: {1}", ex.GetType(), ex.Message); 
    } 
} 


public class SomeProcess 
{ 
    private readonly ConcurrentQueue<Exception> _exceptions; 

    public SomeProcess(ConcurrentQueue<Exception> exceptions) 
    { 
     _exceptions = exceptions; 
    } 

    public void InitSomeProcess() 
    { 
     Parallel.For(0, 20, (i, b) => 
           { 
            try 
            { 
             Console.WriteLine("Initializing SomeProcess on {0}.", i); 
             throw new InvalidOperationException("SomeProcess was unable to Initialize " + i); 
            } 
            catch (Exception ex) 
            { 
             _exceptions.Enqueue(ex); 
            } 
           }); 

     Console.WriteLine("SomeProcess initialized :D"); 
    } 

    public void DoSomeProcess() 
    { 
     Parallel.For(0, 20, (i, b) => 
           { 
            try 
            { 
             Console.WriteLine("Doing SomeProcess on {0}.", i); 
             throw new InvalidOperationException("SomeProcess was unable to process " + i); 
            } 
            catch (Exception ex) 
            { 
             _exceptions.Enqueue(ex); 
            } 
           }); 

     Console.WriteLine("SomeProcess done :D"); 
    } 


} 

public class SomeOtherProcess 
{ 

    private readonly ConcurrentQueue<Exception> _exceptions; 

    public SomeOtherProcess(ConcurrentQueue<Exception> exceptions) 
    { 
     _exceptions = exceptions; 
    } 

    public void InitSomeOtherProcess() 
    { 
     Parallel.For(0, 20, (i, b) => 
           { 
            try 
            { 
             Console.WriteLine("Initializing SomeOtherProcess on {0}.", i); 
             throw new InvalidOperationException("SomeOtherProcess was unable to Initialize " + i); 
            } 
            catch (Exception ex) 
            { 
             _exceptions.Enqueue(ex); 
            } 
           }); 

     Console.WriteLine("SomeOtherProcess initialized :D"); 
    } 

    public void DoSomeOtherProcess() 
    { 
     Parallel.For(0, 20, (i, b) => 
           { 
            try 
            { 
             Console.WriteLine("Doing SomeOtherProcess on {0}.", i); 
             throw new InvalidOperationException("SomeOtherProcess was unable to process " + i); 
            } 
            catch (Exception ex) 
            { 
             _exceptions.Enqueue(ex); 
            } 
           }); 

     Console.WriteLine("SomeOtherProcess done! :D"); 
    } 

} 

답변

1

이 병렬 루프 ... 내부 작업에 의해 던져진 예외를 처리 할 수있는 좋은 방법이라고 생각합니다.

'SomeProcess'에 대해 말하기가 어렵습니다. 이는 비즈니스 규칙과 기술적 인 문제의 조합에 달려 있습니다.

TPL은 Tasks 내에서 예외를 수집하고 호출자에게 알리는 훌륭한 메커니즘을 제공하므로 실제로 필요한 것을 생각해보십시오.


편집, 포맷이 고정 된 후에 : 당신이 당신의 루프가 예외 후 다음 항목을 계속해야한다고 정말 확신한다면

은 다음 대기열 접근 방식은 허용 보인다. 다시 말하지만, 루프가 무엇을하는지에 따라 다릅니다.

+0

예, 반복이 예외를 throw하더라도 mi 루프가 계속되어야합니다. 각 반복은 일부 객체 상태 (예 : 웹 서비스 호출 또는 데이터베이스 쿼리)를 업데이트하고 비즈니스 규칙으로 인해 병렬로 수행해야합니다. – Pato

+0

고마워요! :) – Pato