0

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()
4

1 に答える 1

1

Polly.ExecuteAsync()は a を返しますTask。anyを使用すると、それ (または他のブロッキング メソッド) を Task呼び出して、完了するか例外をスローするまで同期的にブロックすることができます。.Wait()

あなたが観察したように、IJob.Execute(...)isn'tasyncであるため、 を使用することはできませんawait。そのため、公開の成否を確認したい場合は、タスクを同期的にブロックする以外に選択肢はありませんIJob.Execute(...)

.Wait()タスクからの例外が再スローされ、AggregateException. これは、Polly によって調整されたすべての再試行が失敗した場合に発生します。

その例外をどうするかを決める必要があります。

  • 呼び出し元に処理させたい場合は、再スローするか、キャッチせずに Quartz ジョブの外にカスケードさせます。

  • から戻る前にそれを処理したい場合は、全体IJob.Execute(...)の周りに. または、Polly の構文を考えてみましょう。実行の最終結果をインスタンスに配置することで、外側の try-catch を提供する必要がなくなります。Polly docoを参照してください。 try {} catch {}.ExecuteAsync(...).Wait().ExecuteAndCaptureAsync(...)PolicyResult


IJob.Execute(...)メッセージの発行が失敗した場所にログを記録することが唯一の目的であり、そのログが戻る前に発生するかどうかを気にしない場合は、さらに別の方法があります。その場合、 を使用する代わりに.Wait()、継続タスクをExecuteAsync()using.ContinueWith(...)にチェーンし、そこでログを処理することができます。私たちはこのアプローチを採用し、失敗したメッセージを特別な「メッセージ ホスピタル」にパブリッシュします。十分な情報を取得して、必要に応じてそのメッセージを後で再パブリッシュするかどうかを選択できるようにします。このアプローチが価値があるかどうかは、メッセージを失わないことがどれだけ重要かによって決まります。


編集:GetAwaiter()無関係です。awaitasyncメソッド 内で魔法のように使用を開始することはできません。

于 2016-09-05T17:23:59.917 に答える