Pergunta

Eu tenho um serviço do Windows que possui vários threads que precisam ser interrompidos antes da parada do serviço. Estou usando este modelo para interromper meus tópicos e sinalizar que eles foram interrompidos:

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

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

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

Quando chega a hora de fechar meu serviço para parar, basta definir o Running para False e Call Set () em todos os Autoresets por aí. Isso indica instantaneamente os threads para parar de dormir ou para parar quando terminarem de processar o que estão trabalhando. Isso funciona muito bem. Mas, a parte que estou mais nervosa é verificar que tudo parou. Isso é o que estou fazendo agora:

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

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

A principal razão pela qual eu não gosto disso é que é baseado no tempo, e se um dos meus tópicos estiver no meio de uma longa operação (o que é bem provável), o desligamento pode não terminar nesses 25 segundos (e é Muito importante que todos esses threads sejam desligados quando no momento, onde esse código é executado, termina). Não posso remover as tentativas, porque se um desses threads está pendurado (eles não, mas você nunca sabe), então estou realmente preso e o serviço nunca vai parar.

Existe uma maneira melhor de fazer a verificação que todos os threads pararam, de preferência um que não seja baseado no tempo? Ou estou fadado a ter algum tipo de tempo limite que possa precisar ser muito mais longo (10 tentativas com um sono de 30 segundos, talvez)?

Foi útil?

Solução

Acredito que o método geral para fazer isso é entrar nos tópicos. As especificidades da chamada dependerão da biblioteca de encadeamento que você está usando, mas em geral o join O método bloqueará até que o encadeamento tenha saído (e retorne imediatamente se o thread já estiver morto). Então, você pode simplesmente participar de todos os seus tópicos em sequência e depois sair. Se todas as suas junções retornaram, todos os threads saíram.

Muitas bibliotecas de encadeamento permitem que você adicione um tempo limite para participar, o que você provavelmente gostaria de fazer. Dessa forma, mesmo que um de seus threads pendure seu código de saída não bloqueie.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top