Pergunta

Eu tenho um controle PictureBox em um formulário que é suposto para desenhar algo a cada 100ms.

Os executa discussão de fundo algum cálculo em um loop e depois de cada iteração, ele dispara um evento.

Editado (como uma resposta a um comentário) :

World world = new World();

void CreateBackgroundThread() {
    Thread backgroundThread = new Thread(world.BackgroundWorkerFunction);
    backgroundThread.Start();
}

public class World { 

    void BackgroundWorkerFunction() {
        IPiece piece = PieceFactory.Create();
        for (int i = 0; i < stepsCount; i++) {
            piece.Calculate();
            if (OnPieceStep != null) {
                OnPieceStep(piece);
            }
        }
    }

}

Dentro do formulário principal, há um manipulador, set por:

world.OnPieceStep += DrawScreen;

e o invólucro Invoke (uma vez que o controle a ser atraídos para, é criado no segmento interface do usuário).

void DrawScreen(IPiece piece) {
    this.Invoke(new PieceStep(_drawScreen), piece);
}
void _drawScreen(IPiece piece) {
    drawer.Draw(world.Board, piece);
}

Agora, eu gostaria que o loop para fazer uma pausa de 100ms após cada iteração, então eu adicionei Thread.Sleep (100); antes de disparar um evento:

for (int i = 0; i < stepsCount; i++) {
    IPiece piece = Calculate();
    if (OnPieceStep != null) {
        Thread.Sleep(100);
        OnPieceStep(piece);
    }
}

Este, porém, não atualiza o pictureBox cada 100 ms, mas chama apenas a última iteração do loop, e somente após a conclusão de loop.

não deve Thread.Sleep pausar o fio é chamado de, não o segmento interface do usuário? Update: Eu apenas tentei clique no aplicativo enquanto as calcula discussão de fundo. Os blocos de programa ( "não respondem"), de modo que o Thread.Sleep foi obviamente chamado UI Thread. É este o comportamento esperado ou algo está errado com a minha segmentação?

Foi útil?

Solução 2

Como afirmado na desta página :

Thread.Sleep é único entre os bloqueando métodos em que suspenda mensagem do Windows bombeamento dentro de um aplicativo Windows Forms ou COM ambiente em um segmento para o qual a modelo de apartamento single-threaded é usava. Este é de pouca importância com aplicações Windows Forms, em que qualquer operação de bloqueio extenso sobre o principal segmento interface do usuário fará com que o não responde aplicação - e é portanto, geralmente evitado - independentemente do se ou não de bombeamento mensagem é "técnica" suspensa. o situação é mais complexa em um legado COM ambiente de hospedagem, onde ele pode por vezes ser desejável para dormir enquanto mantendo mensagem de bombeamento vivo. discute Chris Brumme da Microsoft isso longamente em seu web log (busca: 'COM "Chris Brumme"').

Parece que Thread.Sleep () em WinForms sempre faz uma pausa a interface do usuário, não importa em qual segmento é chamado.

Outras dicas

De enfiar prospectivo tudo parece bem. Mais provável problema se baseia no método _drawScreen (peça IPiece). Você já tentou atualizar / actualizar a janela depois de desenhar?

Alguns insight: método Control.Invoke passa delegado fornecido como um parâmetro como uma mensagem de janela usando a função Win32 SendMessage.

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