我正在开发一个预定作业,使用Quartz.net将消息发送到消息队列。 IJob的Execute方法不是异步的。所以我不能使用异步任务。但是我想用await关键字调用一个方法。
请在下面找到我的代码。不确定我是否做得对。有人可以帮我这个吗?
private async Task PublishToQueue(ChangeDetected changeDetected)
{
_logProvider.Info("Publish to Queue started");
try
{
await _busControl.Publish(changeDetected);
_logProvider.Info($"ChangeDetected message published to RabbitMq. Message");
}
catch (Exception ex)
{
_logProvider.Error("Error publishing message to queue: ", ex);
throw;
}
}
public class ChangedNotificatonJob : IJob
{
public void Execute(IJobExecutionContext context)
{
//Publish message to queue
Policy
.Handle<Exception>()
.RetryAsync(3, (exception, count) =>
{
//Do something for each retry
})
.ExecuteAsync(async () =>
{
await PublishToQueue(message);
});
}
}
这是正确的方法吗?我用过.GetAwaiter();
Policy
.Handle<Exception>()
.RetryAsync(_configReader.RetryLimit, (exception, count) =>
{
//Do something for each retry
})
.ExecuteAsync(async () =>
{
await PublishToQueue(message);
}).GetAwaiter()
答案 0 :(得分:1)
Polly&#39; .ExecuteAsync()
返回Task
。对于任何Task
,您只需在其上调用.Wait()
(或其他阻塞方法)即可同步阻塞,直到完成或抛出异常。
正如您所观察到的,由于IJob.Execute(...)
不是async
,因此您无法使用await
,因此您别无选择,只能同步阻止任务,如果你想在IJob.Execute(...)
返回之前发现成功或否则发布。
.Wait()
将导致任务中的任何异常被重新引发,并包含在AggregateException
中。如果所有Polly-orchestrated重试都失败,则会发生这种情况。
您需要决定如何处理该异常:
如果您希望调用者处理它,请重新抛出它或者不要捕获它并让它在Quartz作业之外级联。
如果您想在从IJob.Execute(...)
返回之前处理它,那么您需要在整个try {} catch {}
周围.ExecuteAsync(...).Wait()
。或者考虑一下Polly的.ExecuteAndCaptureAsync(...)
语法:它避免了你必须提供外部try-catch,而是将执行的最终结果放入PolicyResult
实例中。请参阅Polly doco。
如果您的唯一目的是记录消息发布失败的地方,并且您不关心在IJob.Execute(...)
返回之前是否发生了日志记录,还有另一种选择。在这种情况下,您可以使用.Wait()
将延续任务链接到ExecuteAsync()
,而不是使用.ContinueWith(...)
,并处理其中的任何日志记录。我们采用这种方法,并将失败的消息发布到一个特殊的消息医院&#39; - 捕获足够的信息,以便我们可以选择是否在以后再次重新发布该消息(如果适用)。这种方法是否有价值取决于它对你永远不会失去信息的重要性。
编辑:GetAwaiter()
无关紧要。它不会神奇地让你开始在非await
方法中使用async
。