处理任务和并行循环中的异常。 (线程 - TPL)
我想知道您是否认为这是处理任务内并行循环(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
很难说“SomeProcess”。这取决于您的业务规则和技术问题的组合。
TPL 有一个出色的机制来收集任务内部的异常并将它们传递给调用者,因此请考虑一下您真正需要什么。
修复格式后进行编辑:
如果您确实确定循环应在异常后继续下一个项目,那么您的
排队方法看起来可以接受。同样,这取决于循环正在做什么。
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.