У меня есть служба TopShelf, которая использует асинхронный код для подключения к веб-службам и другим серверам приложений.Как обрабатывать ошибки async Start() в TopShelf
Если он не может инициализировать свои соединения при запуске, служба должна регистрировать некоторые ошибки и изящно останавливаться.
Я смотрел на this question об остановке TopShelf, когда условия запуска не выполняются. 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();
}
}
Это, кажется, работает хорошо. Но я использую ключевое слово ожидания в нескольких местах в функции. Поэтому я не могу просто изменить свой метод Start()
, чтобы взять HostControl
и вернуть bool
, потому что мне нужно было бы вернуть Task<bool>
из метода async
.
В настоящее время я разрешаю исключениям из функции Start(), чтобы TopShelf мог их видеть и автоматически останавливать службу, когда исключение пузырится вверх. Тем не менее, исключения теперь полностью не обрабатываются моим кодом, и поэтому я получаю неприятные необработанные сообщения об ошибках исключения в различных журналах, которые я пишу. Который я бы предпочел заменить хорошим сообщением об ошибке и отключением чистой службы.
Итак, у меня есть два вопроса:
- Есть ли какие-либо проблемы с использованием
async void Start()
метод Topshelf? - Есть ли способ сделать это так, чтобы, если
Init()
выбрасывает исключение, детали исключения изящно регистрируются, а затем служба останавливается, учитывая, что моя служба запускает кодasync
?
Как я могу убедиться, что '_serviceTask', возвращаемый' ExecuteAsync() ', фактически запускается, не ожидая его в методе' Start() '? Я не могу ждать его там, потому что для этого потребуется 'Start()' async. В тестовом коде с помощью метода 'Poll()', основанного на 'Task.Delay()', когда я вызываю '_serviceTask.Start()', 'InvalidOperationException' выдается с сообщением' Start 'может не вызываться на обещание в стиле. «Если я не жду или не запустил задачу, она, похоже, останется в состоянии« WaitingForActivation »? – Hydrargyrum
Ничего, мой тестовый код сосать. ExecuteAsync() возвращает запущенную задачу, поэтому мне не нужно ничего делать, чтобы ее запустить. Я не уверен, почему статус Task был «WaitingForActivation», а не запущен, но задача действительно выполняется и в конечном итоге завершается. – Hydrargyrum
Одна из проблем с этим, если ExecuteAsync выбрасывает исключение, это никогда не будет замечено? – Peter