Почему Task.Run () в службе Windows OnStart () приводит к отказу службы остановить? - PullRequest
0 голосов
/ 27 февраля 2019

Я не уверен, почему эта служба отказывается останавливаться.

Я столкнулся с этим при попытке исправить TimeoutException, выброшенный при запуске службы.Использование:

public void OnStart()
{
    _startTask = Task.Run(DoWork, _cancelTokenSource.Token);
}

private void DoWork(){ [listen for things and operate on them] }

public void OnStop()
{
    _cancelTokenSource.Cancel();
    _startTask.Wait();
}

Я понимаю, что реализация простого таймера решит эту проблему, но это не главное в моем вопросе.Почему использование Task.Run(() => action, _tokenSource.Token) разрешает TimeoutException, но заставляет службу не отвечать на управляющие сообщения?

Наблюдаемая проблема

После установки и запуска службы (это TopShelf BTW)Я не могу остановить службу обычными способами.

Первая попытка:

enter image description here

Все последующие попытки:

enter image description here

Редактировать: Все еще нет радости

Вот моя попытка после приведенного предоставленного примера .

public void Start()
{
    var token = _cancelTokenSource.Token;
    Task.Factory.StartNew(() => Setup(token), token);
}

public void Stop()
        {
            _cancelTokenSource.Cancel();
            //TearDown(); <-- original implementation of stop
        }

private void Setup(CancellationToken token)
        {
            _mailman.SendServiceStatusNotification(_buildMode, "Started");
            ... create some needed objects

            token.Register(TearDown);

            InitializeInboxWatcherProcess(...);

        }

private void TearDown()
        {
            _inboxWatcher.Terminate();
            _mailman.SendServiceStatusNotification(_buildMode, "Stopped");
        }

private void InitializeInboxWatcherProcess(...)
        {
            // pre create and initiate stuff
            _inboxWatcher = new LocalFileSystemWatcherWrapper(...);
            _inboxWatcher.Initiate();
        }

public class LocalFileSystemWatcherWrapper : IFileSystemWatcherWrapper
    {
        // do FileSystemWatcher setup and control stuff
    }

1 Ответ

0 голосов
/ 27 февраля 2019

Это наиболее вероятно, потому что у вас либо нет метода отмены, либо внутри DoWork() есть подпроцессы, которые все еще работают, когда вы вызываете Cancel().Как сказал @Damien_The_Unbeliever, отмена - это совместная задача.

Когда вы вызываете _cancelTokenSource.Cancel(), если вы не зарегистрировали функцию обратного вызова, все, что происходит, это то, что булево значение isCancellationRequested установлено в true, DoWork() Метод отвечает за то, чтобы увидеть это и остановить его выполнение самостоятельно.Однако здесь есть недостаток, который, как вы, вероятно, можете сказать, заключается в том, что если в задаче DoWork() при вызове Cancel() выполняется трудоемкий цикл, этот цикл должен завершить итерацию, прежде чем сможет проверить значение.isCancellationRequested, что может привести к зависанию.

Способ обойти это - вставить функции обратного вызова отмены в метод DoWork(), см. здесь и затем зарегистрировать их в токене, так чточто при вызове метода Cancel() ВСЕ задачи, работающие в фоновом режиме, останавливаются без ожидания их.

Надеюсь, это поможет!

...