Объясните, почему "использование" не будет работать на службе?

Итак, я застрял в этой проблеме около недели. Я пытался запустить проект, чтобы получить TCP-соединение и запустить концентратор SignalR в качестве службы. Оба отлично работали над проектом как файл .exe. Часть TCP будет работать отлично, однако у меня были проблемы со стороной SignalR.

Причиной стало применение с помощью.

До

using (WebApp.Start<SignalrStartup>(url))
{
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("Server running on {0}", url); // was url
    Console.WriteLine("ID\tMessage");
    Console.ReadLine();
}

После

WebApp.Start<SignalrStartup>(url);

Я попробовал запустить код с Console.WriteLine() закомментированным, так как я думал, что это может вызвать исключение, так как консоль не выводится для запуска в качестве службы. Это также не сработало, но также не работало как файл .exe, так как ему нужно было Console.ReadLine(), чтобы консоль открывалась, вроде того, как вам нужно, чтобы сохранить HelloWorld.cs. После удаления с использованием оболочки вместе с консолью она будет работать как в .exe, так и в сервисе.

Я прочитал, что оператор с использованием убивает объекты в нем, как только вы покидаете оболочку. Но я не понимаю, как бит после держит код .exe открытым после запуска. Есть ли смысл использовать с помощью, или я использовал его неправильно?

Edit

protected override void OnStart(string[] args)
{
    Task.Factory
        .StartNew(() => StartTCP())
        .ContinueWith(t => StartSignalR());
}

Вызов выполняется из метода StartSignalR().

Ответы

Ответ 1

Что происходит с вашей услугой?

Проблема, с которой вы столкнулись, заключается в том, что ваш Console.ReadLine блокирует ожидание стандартного ввода. Это будет заблокировано навсегда в службе Windows и заставит диспетчер управления службами отключить запуск службы через 30 секунд. Этот вопрос содержит больше информации о том, что происходит.

Если вы удалите все содержимое оператора using, и сам оператор, как вы это делали, сервер, который был запущен с помощью WebApp.Start, продолжит работу в фоновом режиме после завершения вашего сервиса Start. Это правильное поведение службы.

То, что вы эффективно делаете здесь, - это утечка асинхронных рабочих, созданных WebApp.Start. Это означает, что они все еще работают после завершения запуска службы для прослушивания запросов.

Вероятно, вы должны отслеживать IDisposable, который возвращает WebApp.Start, и удалять его в методе Stop.

Что о using?

A using statement гарантирует, что ресурс всегда удаляется, когда элемент управления оставляет блок using. Это может быть либо из-за того, что выбрано исключение, либо потому, что блок успешно завершен, и управление переходит к следующей части программы.

Операторы

using используются, когда вы знаете, что ничто не хочет получить доступ к ресурсу после завершения блока. Обычно это происходит, когда вы имеете дело с методами, которые возвращают вам IDisposable. В вашем случае, однако, вы не хотите вызывать dispose, потому что хотите, чтобы потоки, созданные WebApp.Start, продолжались после запуска службы.

Ответ 2

Webapp.Start < > запускает рабочие потоки. Эти потоки поддерживают работу exe, даже после завершения выполнения кода в вашем HelloWorld.cs. Ваш exe не будет закрыт, пока все рабочие потоки не будут остановлены.

Когда вы добавляете свое "использование" -statement, фреймворк вызывается Dispose в вашем приложении SignalR. Этот вызов остановит все рабочие потоки, и ваш exe завершится.

Оператор Readline() останавливает приложение в достижении конца инструкции using. Это означает, что метод dispose не вызывается до тех пор, пока вы не нажмете enter.

Итак, для exe вы обычно хотите использовать ReadLine так, как вы. Для службы, которую вы хотите сохранить ссылку на ваш IDisposable, и вызовите на нее утилиту в методе Stop().