Comment faire en sorte que Sleep sur le fil de fond fonctionne avec Invoke
-
06-07-2019 - |
Question
J'ai un contrôle PictureBox sur un formulaire qui est supposé dessiner quelque chose toutes les 100 ms.
Le thread d'arrière-plan effectue des calculs dans une boucle et déclenche un événement après chaque itération.
Modifié (en réponse à un commentaire) :
World world = new World();
void CreateBackgroundThread() {
Thread backgroundThread = new Thread(world.BackgroundWorkerFunction);
backgroundThread.Start();
}
& nbsp;
public class World {
void BackgroundWorkerFunction() {
IPiece piece = PieceFactory.Create();
for (int i = 0; i < stepsCount; i++) {
piece.Calculate();
if (OnPieceStep != null) {
OnPieceStep(piece);
}
}
}
}
Dans le formulaire principal, il y a un gestionnaire, défini par:
world.OnPieceStep += DrawScreen;
et le wrapper Invoke (étant donné que le contrôle sur lequel dessiner est créé, est créé dans le thread d'interface utilisateur).
void DrawScreen(IPiece piece) {
this.Invoke(new PieceStep(_drawScreen), piece);
}
void _drawScreen(IPiece piece) {
drawer.Draw(world.Board, piece);
}
Maintenant, j'aimerais que la boucle for suspende 100 ms après chaque itération. J'ai donc ajouté Thread.Sleep (100); avant de tirer un événement:
for (int i = 0; i < stepsCount; i++) {
IPiece piece = Calculate();
if (OnPieceStep != null) {
Thread.Sleep(100);
OnPieceStep(piece);
}
}
Cependant, cela n’actualise pas la PictureBox toutes les 100 ms, mais ne dessine que la dernière itération de la boucle, et seulement après la fin de la boucle.
Thread.Sleep ne devrait-il pas suspendre le thread sur lequel il est appelé, pas le thread UI? & nbsp; Mise à jour : je viens d'essayer de cliquer sur l'application pendant que le fil d'arrière-plan calcule. Le programme se bloque ("ne répond pas"), donc le Thread.Sleep était évidemment appelé sur UI Thread. Est-ce que ce comportement attendu ou quelque chose ne va pas avec mon threading?
La solution 2
Comme indiqué sur la cette page :
Thread.Sleep est unique parmi les méthodes de blocage qui suspend Pompage de messages Windows dans un Application Windows Forms ou COM environnement sur un fil pour lequel le modèle d'appartement simple thread est utilisé. Cela n'a que peu d'importance avec les applications Windows Forms, en que toute longue opération de blocage sur le fil principal de l'interface utilisateur fera la l'application ne répond pas & # 8211; et est donc généralement évité & # 8211; indépendamment du message pompage ou non est " techniquement " suspendu. le la situation est plus complexe dans un héritage Environnement d'hébergement COM, où il peut parfois être souhaitable de dormir tout garder le message en vie. Chris Brumme de Microsoft discute ceci dans son journal Web (recherche: 'COM "Chris Brumme"'.
Il semble que Thread.Sleep () dans WinForms met toujours l'interface utilisateur en pause, quel que soit le fil appelé.
Autres conseils
De filetage prospective tout va bien. Le problème le plus probable repose sur la méthode _drawScreen (IPiece piece). Avez-vous essayé d'actualiser / mettre à jour la fenêtre après avoir dessiné?
Quelques idées: La méthode Control.Invoke transmet le délégué fourni en tant que paramètre sous forme de message à l’aide de la fonction Win32 SendMessage.