J'ai passé toute la journée à essayer de faire en sorte que mon application utilise des threads, mais sans succès. J'ai lu beaucoup de documentation à ce sujet et j'obtiens toujours beaucoup d'erreurs, alors j'espère que vous pourrez m'aider.
J'ai une méthode qui prend beaucoup de temps et qui appelle la base de données et met à jour l'interface graphique. Cela doit se produire en permanence (ou toutes les 30 secondes environ).
public class UpdateController
{
private UserController _userController;
public UpdateController(LoginController loginController, UserController userController)
{
_userController = userController;
loginController.LoginEvent += Update;
}
public void Update()
{
BackgroundWorker backgroundWorker = new BackgroundWorker();
while(true)
{
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerAsync();
}
}
public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
_userController.UpdateUsersOnMap();
}
}
Avec cette approche, j'obtiens une exception parce que le backgroundworker n'est pas un thread STA (mais d'après ce que j'ai compris, c'est ce que je devrais utiliser). J'ai essayé avec un thread STA et cela a donné d'autres erreurs.
Je pense que le problème vient du fait que j'essaie de mettre à jour l'interface graphique tout en effectuant l'appel de la base de données (dans le fil d'arrière-plan). Je devrais seulement faire l'appel de la base de données et ensuite, d'une manière ou d'une autre, revenir au thread principal. Après l'exécution du thread principal, il devrait revenir au thread d'arrière-plan et ainsi de suite. Mais je ne vois pas comment faire cela.
L'application devrait mettre à jour l'interface graphique juste après l'appel à la base de données. Les événements Firering ne semblent pas fonctionner. Le thread d'arrière-plan ne fait que les saisir.
EDITAR:
De très bonnes réponses :) Voici le nouveau code :
public class UpdateController{
private UserController _userController;
private BackgroundWorker _backgroundWorker;
public UpdateController(LoginController loginController, UserController userController)
{
_userController = userController;
loginController.LoginEvent += Update;
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += backgroundWorker_DoWork;
_backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
}
public void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
_userController.UpdateUsersOnMap();
}
public void Update()
{
_backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//UI update
System.Threading.Thread.Sleep(10000);
Update();
}
public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Big database task
}
}
Mais comment puis-je faire en sorte que cela fonctionne toutes les 10 secondes ? System.Threading.Thread.Sleep(10000) ne fera que figer mon interface graphique et la boucle while(true) dans Update() comme suggéré donne une exception (Thread trop occupé).
2 votes
Vous ne pouvez pas appeler Sleep sur le thread de l'interface utilisateur - vous devez utiliser une minuterie, plus précisément DispatcherTimer.
0 votes
Pourquoi pokez-vous le thread de l'interface utilisateur quand il y a un BackgroundWorker ? :) Et je suis très heureux que vous ayez posé cette question avec beaucoup d'efforts car elle me/nous profite aujourd'hui.
0 votes
J'avais des problèmes avec la progression du rapport. Il est important de "_backgroundWorker.ReportProgress(p, param) ;" dans DoWork().