c# - 在 C# 中实现 Retry Wrapper 的最佳方法是什么?

标签 c# task-parallel-library

我们目前有一个简单的 RetryWrapper,它在发生异常时重试给定的函数:

public T Repeat<T, TException>(Func<T> work, TimeSpan retryInterval, int maxExecutionCount = 3) where TException : Exception
{ 
   ... 

对于 retryInterval,我们使用以下逻辑在下一次尝试之前“等待”。

_stopwatch.Start();
while (_stopwatch.Elapsed <= retryInterval)
{
  // do nothing but actuallky it does! lots of CPU usage specially if retryInterval is high
}
_stopwatch.Reset();

我不是特别喜欢这种逻辑,理想情况下我更希望重试逻辑不要发生在主线程上,你能想出更好的方法吗?

注意:我很乐意考虑 .Net >= 3.5 的答案

最佳答案

只要您的方法签名返回 T,主线程就必须阻塞,直到所有重试完成。但是,您可以通过让线程休眠而不是执行手动重置事件来减少 CPU:

Thread.Sleep(retryInterval);

如果你愿意改变你的API,你可以这样做,这样你就不会阻塞主线程。例如,您可以使用异步方法:

public async Task<T> RepeatAsync<T, TException>(Func<T> work, TimeSpan retryInterval, int maxExecutionCount = 3) where TException : Exception
{
     for (var i = 0; i < maxExecutionCount; ++i)
     {
        try { return work(); }
        catch (TException ex)
        {
            // allow the program to continue in this case
        }
        // this will use a system timer under the hood, so no thread is consumed while
        // waiting
        await Task.Delay(retryInterval);
     }
}

这可以同步消费:

RepeatAsync<T, TException>(work, retryInterval).Result;

不过,您也可以先启动任务,然后再等待:

var task = RepeatAsync<T, TException>(work, retryInterval);

// do other work here

// later, if you need the result, just do
var result = task.Result;
// or, if the current method is async:
var result = await task;

// alternatively, you could just schedule some code to run asynchronously
// when the task finishes:
task.ContinueWith(t => {
    if (t.IsFaulted) { /* log t.Exception */ }
    else { /* success case */ }
});

关于c# - 在 C# 中实现 Retry Wrapper 的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22633044/

相关文章:

.net-4.0 - TPL - MaxDegreeOfParallelism 和 MaximumConcurrencyLevel 之间的区别

C# 字节数组到固定 int 指针

c# - 使用 Parallel ForEach 进行本地初始化如何工作?

c# - 如何使用任务并行库从SQL表中批量读取大量记录

c# - 使用响应式(Reactive)扩展,我可以创建可观察的订阅者,该订阅者会阻塞直到满足某些条件或发生超时

c# - Azure SQL 数据库连接问题 - 连接太多?

C# 插入 MDB 数据库获取最后插入 ID

c# - 如何将 DateTime 格式化为网络 UTC 格式?

c# - 两个 BST 叶子之间的节点之和

c# - 只初始化一次异步模式