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

发布于 2024-12-07 09:00:03 字数 5375 浏览 0 评论 0原文

我想知道您是否认为这是处理任务内并行循环(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");
    }

}

I want to know if you think this is a good way to handle exceptions thrown by Parallel Loops (Parallel.ForEach and/or Parallel.For) inside Tasks.

I think it isn't so bad, but your opinion can be usefull to me! Hope you can throw some light on me!

(I used VS2010 and, of course, 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");
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴梦一场 2024-12-14 09:00:03

如果您认为这是处理任务内并行循环抛出的异常的好方法。

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

TPL 有一个出色的机制来收集任务内部的异常并将它们传递给调用者,因此请考虑一下您真正需要什么。


修复格式后进行编辑:

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

if you think this is a good way to handle exceptions thrown by Parallel Loops ... inside Tasks.

Hard to tell for 'SomeProcess'. This depends on a combination of your business rules and technical issues.

The TPL has an excellent mechanism to collect exceptions inside Tasks and pro[agate them to the caller, so think about what you really need.


Edit, after the formatting was fixed:

If you are really sure that your loop should continue with the next item after an exception then your
enqueue approach looks acceptable. Again, it depends on what the loop is doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文