Webサービスや他のアプリケーションサーバーに接続するために非同期コードを使用するTopShelfサービスがあります。TopShelfで非同期Start()エラーを処理する方法
起動時に接続を初期化できない場合は、サービスでエラーが記録され、正常に停止する必要があります。
開始条件が満たされていないときにTopShelfを停止することについて私はthis questionを見ました。 This answerは、TopShelf HostControlを使用してサービスを停止する方法について説明しています。
しかし、その答えはServiceConfigurator<T>.WhenStarted<T>(Func<T, HostControl, bool> start)
メソッドに依存しています。
私は現在、標準的な方法でTopShelfサービスを設定しています:
x.Service<MyService>(s =>
{
s.ConstructUsing(() => new MyService());
s.WhenStarted(s => s.Start());
s.WhenStopped(s => s.Stop());
});
私のサービスのStart()
方法は次のように定義され、実際にasync
あるしかし:
public async void Start()
{
await Init();
while (!_canceller.Token.IsCancellationRequested)
{
await Poll();
}
}
これは正常に動作するようです。しかし、関数のいくつかの場所でawaitキーワードを使用します。だから、Start()
メソッドをHostControl
に変更してbool
を返すだけでは、をasync
メソッドから返す必要があるため、単純に変更することはできません。
私は現在、例外が起きたときにTopShelfがそれらを見て、自動的にサービスを停止できるように、Start()関数からバブルアップすることを許可しています。しかし、例外は私のコードでは完全に処理されていないので、私が書き込むさまざまなログに、扱いにくい例外エラーメッセージが残ることになります。どちらが良いエラーメッセージとクリーンなサービスシャットダウンで置き換えることを好むでしょう。
- TopShelfため
async void Start()
方法を使用してに問題がある:だから、私は2つの質問がありますか?
Init()
が例外をスローした場合、例外サービスの詳細は正常に記録され、サービスは停止します。私のサービスではasync
コードが実行されていますか?
'ExecuteAsync()'によって返された '_serviceTask'が' Start() 'メソッドで待たずに実際に起動することを確認するにはどうしたらいいですか? 'Start()'が非同期でなければならないので、私はそこで待つことができません。 'Task.Delay()'をベースにした模擬 'Poll()'メソッドを使ったテストコードでは、 '_serviceTask.Start()'を呼び出すと、 'InvalidOperationException'というメッセージがスローされます。私がタスクを待っていない、または開始していなければ、WaitingForActivation状態にとどまっているようです。 – Hydrargyrum
気にしないでください、私のテストコードが吸い込まれました。 ExecuteAsync()は実行中のタスクを返しますので、起動するために特別な操作を行う必要はありません。タスクのステータスが「WaitingForActivation」ではなく実行中である理由が分からないが、タスクが実際に実行されて最終的に完了する。 – Hydrargyrum
ExecuteAsyncが例外をスローした場合、これは決して気付かれません。 – Peter