Pergunta

Estou usando C# com Compact Framework 2, SP2.

O sistema operacional do dispositivo foi configurado para inicializar meu aplicativo, vamos chamar o aplicativo de "Loader.exe".

Carregador é simplesmente isto:um formulário único e simples que mostra mensagens de status durante o carregamento, se necessário (termos leigos para haver um erro e uma mensagem de exceção, ou "iniciando o aplicativo [xyz]"), e uma máquina de estado rodando em segundo plano enquanto um completo básico - o formulário da tela é mostrado.

Portanto, o construtor do formulário do Loader tem o seguinte no muito fim:

try
{
    label1.Text = "Starting GUI Init Thread...";  //debug only message
    System.Threading.Timer guiInit = new System.Threading.Timer(
        RunStateMachine, null, 2000, System.Threading.Timeout.Infinite
        );
    //callback: RunStateMachine, null argument
    //initial callback is 2000ms from this point, and doesn't run again.
}
catch (Exception ex1)
{
    label1.Text = "GUI Init Error 2";
    Failure_Label.Text = ex1.Message;
}

E "RunStateMachine" funciona em um thread diferente da UI, permitindo que o formulário seja exibido, e sempre que RunStateMachine precisa interagir com o formulário, como atualizar mensagens, eu chamo uma função que usa if(this.InvokeRequired){this .Invoke(...);}else{...}

Então, meu problema?
Intermitentemente, meu programa irá travar porque o cronômetro não acionou um retorno de chamada.Eu adicionei a mensagem de depuração no bloco de tentativa acima, junto com muitos outros lugares para me dizer onde ele desligou, incluindo uma mensagem no início de "RunStatemachine". Eventualmente, meu programa estava na mensagem "Tópico inicial da GUI Init ..."

Isso me diz que o temporizador do thread não está executando o um hora que eu preciso.
Minha teoria é que o lixo está sendo coletado antes do cronômetro acionar o retorno de chamada.Isso significaria que se o cronômetro fosse global e, em seguida, descartado explicitamente quando eu chegar ao RunStateMachine, ele funcionaria perfeitamente...mas não quero pensar que resolvi o problema apenas para descobrir que isso acontecerá de forma intermitente daqui a um mês.

Pensamentos?

Foi útil?

Solução

Minha teoria é que ela está sendo coletada de lixo antes do timer desencadeando o retorno de chamada.Isso significaria se o cronômetro fosse global e depois se descartasse explicitamente quando eu chegar ao RunStatemachine, que ela correu perfeitamente ...Mas não quero pensar que resolvi isso apenas para encontrar isso intermitentemente daqui a um mês.

Parece que você deseja a confirmação de que este é o seu problema. Sim, este é o problema.

O temporizador é armazenado em uma variável local que nunca mais é usada.Isso o torna elegível para GC.A GC do temporizador leva à finalização, fazendo com que o temporizador seja desativado.

Sugiro que você armazene o cronômetro em um campo de instância da sua classe de formulário e remova-o de lá assim que o retorno de chamada for acionado.

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