2011-09-29 56 views
2

我想知道如果您認爲這是處理任務內並行循環(Parallel.ForEach和/或Parallel.For)引發的異常的好方法。處理任務和並行循環中的異常。 (Threading - TPL)

我認爲這並不壞,但你的意見可以對我有用!希望你可以給我一些啓示!

(我用VS2010,當然,框架4.0)

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和pro內的異常[把它們分配給調用者,所以想想你真正需要什麼。


編輯後的格式是固定的:

如果你真的確定你的循環應該異常後的下一個項目,然後繼續你的 排隊方法看起來可以接受的。同樣,這取決於循環在做什麼。

+0

是的,即使有任何迭代拋出異常,mi循環也必須繼續。每次迭代都會更新一些對象狀態(例如調用Web服務或查詢數據庫等),並且由於我的業務規則,我需要在並行中執行此操作。 – Pato

+0

非常感謝! :) – Pato