Какой лучший способ определить, что потоки остановились? - PullRequest
1 голос
/ 29 сентября 2010

У меня есть служба Windows, в которой есть несколько потоков, которые необходимо остановить до остановки службы. Я использую эту модель для остановки своих потоков и оповещения о том, что они были остановлены:

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
    Thread1Running = true;

    try
    {
        while (running)
        {
            AutoReset1.WaitOne(TimeSpan.FromSeconds(30.0));

            if (running)
            {
                // do stuff
            }
        }
    }
    finally
    {
        Thread1Running = false;
    }
}));

Когда приходит время выключить мой сервис, я просто устанавливаю значение false и вызываю Set () для всех AutoResets. Это немедленно сигнализирует потокам о том, что они перестают спать или останавливаются после того, как они закончили обработку того, над чем они работают. Это работает очень хорошо. Но то, что меня больше всего волнует, это проверка того, что все прекратилось. Вот что я делаю сейчас:

Int32 tries = 0;
while (tries < 5 && (Thread1Running || Thread2Running || Thread3Running))
{
    tries++;

    Thread.Sleep(TimeSpan.FromSeconds(5.0));
}

Основная причина, по которой мне это не нравится, заключается в том, что он основан на времени, и если один из моих потоков находится в середине длительной операции (что весьма вероятно), завершение может не завершиться в эти 25 секунд. (и очень важно, чтобы все эти потоки были закрыты к тому моменту, когда OnStop, когда этот код запускается, завершается). Я не могу удалить попытки, потому что если один из этих потоков зависает (они этого не делают, но вы никогда не знаете), то я действительно застрял, и служба никогда не остановится.

Есть ли лучший способ проверки того, что все потоки остановлены, предпочтительно не основанный на времени? Или я обречен на какой-то тайм-аут, который, возможно, просто должен быть намного длиннее (возможно, 10 попыток с 30-секундным сном)?

1 Ответ

1 голос
/ 29 сентября 2010

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

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

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