处理任务和并行循环中的异常。 (线程 - TPL)

时间:2011-09-29 14:22:26

标签: c# multithreading c#-4.0 task task-parallel-library

我想知道您是否认为这是处理Tasks内部并行循环(Parallel.ForEach和/或Parallel.For)抛出的异常的好方法。

我认为这不是很糟糕,但你的意见对我有用!希望你能对我有所启发!

(我使用VS2010,当然还有Framework 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 个答案:

答案 0 :(得分:1)

  

如果您认为这是处理Parallel Loops抛出的异常的好方法......在任务中。

很难说'SomeProcess'。这取决于您的业务规则和技术问题的组合。

TPL有一个很好的机制来收集任务中的异常并亲[将它们交给调用者,所以想想你真正需要什么。


修改格式后编辑:

如果您确定您的循环应该在异常后继续下一个项目,那么您的 入队方法看起来可以接受。同样,它取决于循环正在做什么。