相关疑难解决方法(0)

编写重试逻辑最干净的方法?

偶尔我需要在放弃之前多次重试一次手术.我的代码是这样的:

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()方法的代码是什么?

.net c#

434
推荐指数
13
解决办法
20万
查看次数

实现可重试块的正确完成

预告:伙计们,这个问题不是关于如何实施重试政策.这是关于正确完成TPL数据流块.

这个问题主要是我之前在ITargetBlock中重试策略的问题的延续.这个问题的答案是@ svick使用TransformBlock(源)和TransformManyBlock(目标)的智能解决方案.剩下的唯一问题是以正确的方式完成此块:等待所有重试首先完成,然后完成目标块.这是我最终得到的结果(它只是一个片段,不要过多关注非线程安全retries集):

var retries = new HashSet<RetryingMessage<TInput>>();

TransformManyBlock<RetryableMessage<TInput>, TOutput> target = null;
target = new TransformManyBlock<RetryableMessage<TInput>, TOutput>(
    async message =>
    {
        try
        {
            var result = new[] { await transform(message.Data) };
            retries.Remove(message);
            return result;
        }
        catch (Exception ex)
        {
            message.Exceptions.Add(ex);
            if (message.RetriesRemaining == 0)
            {
                if (failureHandler != null)
                    failureHandler(message.Exceptions);

                retries.Remove(message);
            }
            else
            {
                retries.Add(message);
                message.RetriesRemaining--;

                Task.Delay(retryDelay)
                    .ContinueWith(_ => target.Post(message));
            }
            return null;
        }
    }, dataflowBlockOptions);

source.LinkTo(target);

source.Completion.ContinueWith(async …
Run Code Online (Sandbox Code Playgroud)

c# task-parallel-library tpl-dataflow

53
推荐指数
1
解决办法
3999
查看次数

将Polly与TPL数据流一起使用

数据处理管道和瞬态故障处理似乎是相辅相成的,所以我很想看看能否获得两个最佳的库,分别是TPL Dataflow和Polly,才能很好地协同工作。

首先,我想将错误处理策略应用于ActionBlock。理想情况下,我想将其封装在具有如下签名的块创建方法中:

ITargetBlock<T> CreatePollyBlock<T>(
    Action<T> act, ExecutionDataflowBlockOptions opts, Polly.Policy policy)
Run Code Online (Sandbox Code Playgroud)

从中简单地policy.Execute进行操作就足够容易了ActionBlock,但是我有以下两个要求:

  1. 在重试的情况下,我不想重试某个项目以使其优先于其他排队的项目。换句话说,当您失败时,您将转到行尾。
  2. 更重要的是,如果重试之前有一个等待期,我不想阻止新项目进入。如果ExecutionDataflowBlockOptions.MaxDegreeOfParallelism已设置,我不希望等待重试的项目根据该最大值进行“计数”。

为了满足这些要求,我想我需要一个“内部” ActionBlock与用户提供的ExecutionDataflowBlockOptions应用,并且一些“外部”块帖项内部块,并应用任何等待和重试逻辑(或任何策略规定)外内部块的上下文。这是我的第一次尝试:

// wrapper that provides a data item with mechanism to await completion
public class WorkItem<T>
{
    private readonly TaskCompletionSource<byte> _tcs = new TaskCompletionSource<byte>();

    public T Data { get; set; }
    public Task Completion => _tcs.Task;

    public void SetCompleted() => _tcs.SetResult(0);
    public void SetFailed(Exception ex) => _tcs.SetException(ex);
} …
Run Code Online (Sandbox Code Playgroud)

c# tpl-dataflow polly

5
推荐指数
0
解决办法
167
查看次数

标签 统计

c# ×3

tpl-dataflow ×2

.net ×1

polly ×1

task-parallel-library ×1