偶尔我需要在放弃之前多次重试一次手术.我的代码是这样的:
int retries = 3;
while(true) {
try {
DoSomething();
break; // success!
} catch {
if(--retries == 0) throw;
else Thread.Sleep(1000);
}
}
Run Code Online (Sandbox Code Playgroud)
我想在一般的重试函数中重写它,如:
TryThreeTimes(DoSomething);
Run Code Online (Sandbox Code Playgroud)
在C#中有可能吗?该TryThreeTimes()方法的代码是什么?
为了避免我可以用Google搜索的所有标准答案,我将提供一个你可以随意攻击的例子.
C#和Java(和太多的人)有很多类型的一些"溢出"的行为,我不都不像(如type.MaxValue + type.SmallestValue == type.MinValue例如: int.MaxValue + 1 == int.MinValue).
但是,看到我的恶性,我会通过扩展这种行为来增加对这种伤害的一些侮辱,让我们说一个Overridden DateTime类型.(我知道DateTime密封在.NET中,但是为了这个例子,我使用的是一种与C#完全相同的伪语言,除了DateTime没有密封的事实).
被覆盖的Add方法:
/// <summary>
/// Increments this date with a timespan, but loops when
/// the maximum value for datetime is exceeded.
/// </summary>
/// <param name="ts">The timespan to (try to) add</param>
/// <returns>The Date, incremented with the given timespan.
/// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and
/// continue from DateTime.MinValue.
/// </returns>
public DateTime override Add(TimeSpan …Run Code Online (Sandbox Code Playgroud) 我需要在工作流程中引入重试策略.假设有3个块以这种方式连接:
var executionOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 3 };
var buffer = new BufferBlock<int>();
var processing = new TransformBlock<int, int>(..., executionOptions);
var send = new ActionBlock<int>(...);
buffer.LinkTo(processing);
processing.LinkTo(send);
Run Code Online (Sandbox Code Playgroud)
因此,有一个缓冲区累积数据,然后将其发送到转换块,该转换块一次处理不超过3个项目,然后将结果发送到操作块.
在处理过程中可能会出现变换块瞬态错误,如果错误是瞬态错误,我想重试该块.
我知道块通常不可重试(传递到块中的委托可以重试).其中一个选项是包装传递给支持重试的委托.
我也知道有一个非常好的库TransientFaultHandling.Core可以为瞬态故障提供重试机制.这是一个很棒的图书馆,但不是我的情况.如果我将传递给转换块的委托包装到RetryPolicy.ExecuteAsync方法中,则转换块内的消息将被锁定,并且在重试完成或失败之前,转换块将无法接收新消息.想象一下,如果所有3条消息都输入到重试中(假设下次重试尝试将在2分钟内完成)并且失败,则变换块将被卡住,直到至少有一条消息离开变换块.
我看到的唯一的解决办法是延长TranformBlock(实际上,ITargetBlock将有足够太),和做手工重试(比如从这里):
do
{
try { return await transform(input); }
catch
{
if( numRetries <= 0 ) throw;
else Task.Delay(timeout).ContinueWith(t => processing.Post(message));
}
} while( numRetries-- > 0 );
Run Code Online (Sandbox Code Playgroud)
ig将消息再次放入变换块中,但是在这种情况下,重试上下文(剩余的重试次数等)也应该传递给该块.听起来太复杂了......
有没有人看到更简单的方法来实现工作流程块的重试策略?