我有一个简单的c#方法,如果在中间抛出任何异常,我想在一段时间后(即2分钟)重新运行/继续该方法,直到它完成。例如,如果在for循环中发生任何异常,我想在一些可配置的时间后运行此方法,而不是抛出异常
public void Process(List<string> msg)
{
foreach(var m in msg) { }
}
通过装饰像这样的东西
[ReRun(Maxtime =5, TimeIntervalInSec=600)]
public void Process(List<string> msg)
{
foreach(var m in msg) { }
}
可以作为Separate类完成,并作为属性插入此方法吗?
答案 0 :(得分:1)
您必须编写 lot 更多(复杂)代码,以使任何内容按照您的布局方式运行。仅使用超时调用辅助方法会更加简单。
你可能应该将它作为一个单独的线程运行,或者你将要&#34;挂起&#34;你在&#34;睡眠期间的主要处理线程&#34;周期。
总的来说,我会质疑你是否需要重新考虑整个方法论。
public void Process(List<string> msg)
{
bool permfail = false;
bool complete = false;
int runCount = 0;
while (!complete && !permfail)
{
try
{
AttemptProcess(msg);
complete = true;
}
catch
{
if (runCount++ > 10)
permfail = true;
else
System.Threading.Thread.Sleep(new TimeSpan(0, 2, 0));
}
}
}
void AttemptProcess(List<string> msg)
{
// Do whatever processing here
}
答案 1 :(得分:1)
如果抛出异常,我会修改调用者再次调用该方法,而不是这样做。单一责任原则表明,管理如何调用它或调用者抛出异常时所做的事情不是一个类的工作。 (但你已经看到了,因为你避免将它直接放在方法中。)
我写了这个并做了一些快速的单元测试。 (我在命名方面很糟糕。)用法是
var execution = new RetryExecution<int>(() => SomeFunctionThatReturnsAnInt());
var result = execution.Execute(2); //specifies maximum number of attempts.
它调用给定方法 n 次并返回值或抛出最后一个异常。 Exceptions
属性返回任何未被删除的异常。
public class RetryExecution<T>
{
private readonly Func<T> _function;
private List<Exception> _exceptions = new List<Exception>();
public RetryExecution(Expression<Func<T>> expression )
{
_function = expression.Compile();
}
public Exception[] Exceptions { get { return _exceptions.ToArray(); } }
public T Execute(int maxAttempts)
{
var attempts = 0;
while (attempts < maxAttempts)
{
attempts++;
try
{
return _function.Invoke();
}
catch (Exception ex)
{
if (attempts >= maxAttempts) throw;
_exceptions.Add(ex);
}
}
return default(T);//Not reachable, but compiler needs it.
}
}