Какой лучший способ определить, что потоки остановлены?
-
26-09-2019 - |
Вопрос
У меня есть служба 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 Call () на всех ауторесах. Это мгновенно сигнализирует темы, чтобы остановить спать или остановиться, как только они закончили обработку, на которых они работают. Это работает очень хорошо. Но часть, о которой я больше всего нервничает, проверяет, что все остановилось. Это то, что я делаю сейчас:
Int32 tries = 0;
while (tries < 5 && (Thread1Running || Thread2Running || Thread3Running))
{
tries++;
Thread.Sleep(TimeSpan.FromSeconds(5.0));
}
Основная причина, по которой мне не нравится, это то, что на основании на основе времени на базе времени, и если одна из моих потоков находится в середине длительной работы (что вполне вероятно), выключение может не закончить в этом 25 секунд (и это Очень важно, чтобы все эти темы были закрыты на время OnStop, где этот код запускается, отделка). Я не могу удалить попытки, потому что, если одна из тех нитей висит (они этого не делают, но вы никогда не знаете), то я действительно застрял, и сервис никогда не остановится.
Есть ли лучший способ сделать подтверждение того, что потоки все останавливаются, предпочтительно то, что это не на основе времени? Или я обречен, чтобы иметь какой-то тайм-аут, который может просто быть намного дольше (10 попыток с 30-дюймовым сон, может быть)?
Решение
Я считаю, что общий метод для этого должен присоединиться к потокам. Специфика вызова будет зависеть от библиотеки Threading, вы используете, но в целом join
Метод будет блокировать до тех пор, пока нить не будет не доведена (и должна немедленно вернуться, если нить уже мертва). Таким образом, вы могли бы просто присоединиться к всем вашим потокам в последовательности, затем выйти. Если все ваши присоединения вернулись, то все темы вышли.
Многие резьбовые библиотеки позволяют добавить тайм-аут, чтобы присоединиться, что вы, вероятно, захотите сделать. Таким образом, даже если одна из ваших потоков зависает ваш код выхода не блокирует.