Ocorre uma ThreadStateException ao tentar reiniciar um thread
-
08-06-2019 - |
Pergunta
De vez em quando recebo uma System.Threading.ThreadStateException ao tentar reiniciar um thread.O código em questão é o seguinte:
// Make sure the thread is done stopping
while (this.mThread.ThreadState == ThreadState.Running)
{
Thread.Sleep(0);
}
// Respawn a thread if the current one is stopped or doesn't exist
if (this.mThread == null || this.mThread.ThreadState == ThreadState.Stopped)
{
this.mThread = new Thread(new ParameterizedThreadStart(Monitor)); }
// Start the thread
if (check)
{
this.mThread.Start(60000);
}
else
{
this.mThread.Start(0);
}
Portanto, duas perguntas: esta é a maneira correta de fazer as coisas e existe uma maneira de evitar que o erro ocorra?
Solução
O problema é que você tem um código que primeiro verifica se deve criar um novo objeto de thread e outro trecho de código que determina se o objeto de thread deve ser iniciado.Devido a condições de corrida e coisas semelhantes, seu código pode acabar tentando chamar .Start em um objeto de thread existente.Considerando que você não publica os detalhes por trás do verificar variável, é impossível saber o que pode desencadear esse comportamento.
Você deve reorganizar seu código para que .Start seja chamado apenas em novos objetos.Resumindo, você deve colocar o método Start na mesma instrução if daquela que cria um novo objeto thread.
Pessoalmente, eu tentaria reorganizar todo o código para não precisar criar outro thread, mas agrupar o código dentro do objeto thread dentro de um loop para que o thread continue funcionando.
Outras dicas
É possível que um thread esteja em mais de um estado ao mesmo tempo, portanto a propriedade ThreadState é na verdade um bitmap de estados possíveis.Portanto, testar a igualdade com apenas um estado não lhe dará o resultado correto.Você precisaria fazer algo como:
if((mThread.ThreadState & ThreadState.Running) != 0)
No entanto, verificar o estado do thread é errado fazer qualquer coisa.Não estou totalmente claro o que você está tentando alcançar, mas acho que você está aguardando o término de um thread antes de reiniciá-lo.Nesse caso você deve fazer:
mThread.Join();
mThread = new Thread(new ParameterizedThreadStart(Monitor));
if(check)
mThread.Start(60000);
else
mThread.Start(0);
Embora se você descrever o problema que está tentando resolver com mais detalhes, tenho quase certeza de que haverá uma solução melhor.Esperar que um thread termine apenas para reiniciá-lo novamente não parece tão eficiente para mim.Talvez você só precise de algum tipo de comunicação entre threads?
John.
Uma ThreadStateException é lançada porque você está tentando iniciar um thread que não está em um estado inicializável.As situações mais prováveis seriam que ele já estivesse em execução ou tivesse sido totalmente encerrado.
Existem potencialmente algumas coisas que podem estar acontecendo.Primeiro, o thread pode ter feito a transição de Running para StopRequested, que ainda não está totalmente parado, então sua lógica não cria um novo thread e você está tentando iniciar um thread que acabou de ser executado ou está prestes a ser executado. terminar a execução (nenhum dos quais é um estado válido para reiniciar).
A outra possibilidade é que o thread tenha sido abortado.Threads que são abortados vão para o estado Abortado, não para o estado Parado e, claro, também não são válidos para reinicialização.
Na verdade, o único tipo de thread que ainda está ativo e que pode ser “reiniciado” é aquele que está suspenso.Você pode querer usar esta condicional:
if (this.mThread == null || this.mThread.ThreadState != ThreadState.Suspended)