Каков текущий правильный способ начать бесконечную обработку l oop в сервисе windows? - PullRequest
0 голосов
/ 31 января 2020

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

В моем методе OnStart я обычно делал бы то же самое ,

new Thread(new ThreadStart(QueueProcessorDoWork));

Так что он начинает поток, а затем сразу возвращается.

А потом:

private void QueueProcessorDoWork()
        {
            while (_isRunning)
            {
                DoStuff();
                Thread.Sleep(100);
            }
        }

Нет способа чтобы сделать DoStuff () блокирующей операцией, он должен опрашивать.

Теперь Thread.Sleep считается плохой практикой, поскольку он блокирует поток.

Итак, исследования показали, что я можно использовать таймер Никаких проблем с этим, я бы создал таймер и установил его опрос каждые 100 мс, а в обработчике таймера я бы отключил таймер, выполнил обработку, снова включил таймер, и у нас все было бы хорошо.

Однако я тогда читал об использовании async / await с Task.Delay(100).

Звучит неплохо. Мне все еще нужно создать Thread, я считаю, потому что в противном случае метод OnStart не вернется. Однако это неясно, если я вызываю асинхронный метод c, не ожидая его, я не знаю, что произойдет.

Таким образом, вопрос 1 - я должен просто вызвать асинхронную c задачу, которая содержит бесконечное l oop, не дожидаясь его запуска моей windows службы?

Если я действительно хочу использовать async / await в потоке, как именно я go могу начать? Мой ThreadStart может вызывать функцию, которая, в свою очередь, выполняет Task.Run(async () => Worker()) или что-то еще, я не уверен, так как абонент должен был бы быть отмечен как asyn c?

Так что вопрос 2 в том, как мне настроить Шаблон async / await в вызове new Thread()?

И последний вопрос: какой (или оба?) из двух методов являются «правильным» способом для запуска бесконечной обработки l oop?

1 Ответ

3 голосов
/ 31 января 2020

Теперь Thread.Sleep считается плохой практикой, поскольку он блокирует поток.

Да и нет. Thread.Sleep не является идеальным , но если вы знаете, что этот код всегда выполняется на настольном компьютере, то один дополнительный поток за время существования процесса довольно дешев. Я не потерял бы сон из-за этого.

Итак, исследование показало, что я могу использовать таймер.

Да, таймер - прекрасное решение.

Однако затем я прочитал об использовании async / await с Task.Delay (100).

Конечно, вы тоже можете это сделать. Внутри Task.Delay просто запускает таймер и завершает задачу при срабатывании таймера. Так что это практически одно и то же.

Мне все еще нужно создать поток, я считаю, потому что в противном случае метод OnStart не вернется. Однако это неясно, если я вызову асинхронный метод c, не ожидая его, я не знаю, что произойдет.

Как только await потребуется (асинхронно) ) дождитесь завершения операции, метод async вернет . Так что если вы сначала измените свой l oop на await Task.Delay, а затем DoStuff, отдельный поток не понадобится. В качестве альтернативы, вы могли бы просто вызвать QueueProcessorDoWork, завернутый в Task.Run, который поставит его в очередь в пул потоков.

Так что вопрос 1 - я должен просто вызвать асинхронную c задачу, которая содержит бесконечное число l oop, не дожидаясь его запуска моей службы windows?

Это одна возможность:

var task = Task.Run(() => QueueProcessorDoWork());

Обратите внимание, что task дополнится исключение, если l oop выдает исключение. Я рекомендую использовать метод «управления», который await выполняет эту задачу и выходит из службы, если она когда-либо завершится:

async Task MainAsync()
{
  try { QueueProcessorDoWork(); }
  catch (Exception ex) { /* log */ }
  finally { /* stop the Win32 service */ }
}

Итак, вопрос 2: как мне настроить асинхронную / ожидающую обработку? шаблон при вызове новой темы ()?

Вы не. Thread.Sleep несколько обескуражен, но new Thread определенно обескуражен. Если вы не используете COM-взаимодействие, вы не должны создавать ручные потоки.

И последний вопрос: какой (или оба?) Из двух методов являются «правильным» способом запуска бесконечная обработка l oop?

Просто делайте то, что работает для вас. Либо таймер, либо Task.Run, упаковывающий oop в Task.Delay, будет работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...