如何为短暂和重复的动作写一个超时?

时间:2017-02-16 19:36:25

标签: c# .net .net-4.0 timeout rabbitmq

我想为RabbitMQ C#客户端的BasicPublish方法编写一个超时函数。由于许多原因,有时队列被阻塞,或者兔子瘫痪或其他什么。但是我想知道发布何时立即失败。我不想出于任何原因阻止该网站。

我担心使用Task或线程为简单发布增加开销来实现超时,我们在生产中已经做了数百万次。

有没有人知道如何在快速阻止方法上写一个快速超时作为BasicPublish?

澄清:我也在.Net 4工作,我没有异步。

2 个答案:

答案 0 :(得分:1)

Polly有一个TimeoutPolicy针对这种情况。

Polly的TimeoutStrategy.Optimistic接近@ ThiagoCustodio的答案,但它也正确处理了toggled。然而,RabbitMQ的C#客户端(在撰写本文时)未提供var toggled = false (document).on('click', '#target', function(e){ if(!toggled){ toggled = true setTimeout(function(){ toggled = false },500) //Do stuff } }); 过载CancellationTokenSource,因此这种方法无关紧要。

Polly的TimeoutStrategy.Pessimistic针对BasicPublish()这样的情况,您希望对 CancellationToken支持的代理施加超时。

Polly的BasicPublish()

[1]允许调用线程超时(远离等待)执行,即使执行的委托不支持取消也是如此。

[2]以额外的任务/线程(在同步执行中)为代价,并为您管理。

[3]也captures the timed-out Task(你已经离开的任务)。这对于日志记录很有用,并且必需以避免UnobservedTaskExceptions - 特别是在.NET4.0中,UnobservedTaskException can bring down your entire process

简单示例:

CancellationToken

正确避免TimeoutStrategy.Pessimistic的完整示例:

Policy.Timeout(TimeSpan.FromSeconds(10), TimeoutStrategy.Pessimistic).Execute(() => BasicPublish(...));

为避免在RabbitMQ不可用的情况下建立太多并发的待处理任务/线程,您可以使用Bulkhead Isolation policy来限制并行化和/或CircuitBreaker以防止通过调用一旦你发现了一定程度的失败。这些可以使用PolicyWrap与TimeoutPolicy结合使用。

答案 1 :(得分:0)

我想说最简单的方法是使用任务/取消令牌。你认为这是一个开销吗?

public static async Task WithTimeoutAfterStart(
    Func<CancellationToken, Task> operation, TimeSpan timeout)
{
    var source = new CancellationTokenSource();
    var task = operation(source.Token);
    source.CancelAfter(timeout);
    await task;
}

用法:

await WithTimeoutAfterStart(
    ct => SomeOperationAsync(ct), TimeSpan.FromMilliseconds(n));