La communication entre les fils principaux et EDT
-
09-09-2019 - |
Question
Je pose beaucoup de questions au sujet d'un projet, je travaille récemment. Voici le scénario que je suis et toute aide ou d'un point dans la bonne direction aiderait beaucoup ...
Ceci est un programme de réseau construit avec un serveur et plusieurs clients. Chaque client dispose d'une interface utilisateur qui doit agir en fonction de commandes envoyées à partir du serveur. Chaque client est enveloppé dans une classe appelée Player
. Cette Player
a une interface utilisateur graphique (étend JFrame
) et une méthode principale, et le serveur a une méthode principale uniquement (pas de GUI). Dans un premier temps, cette classe a été créée dans le thread principal comme ceci:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
Ce fonctionnait bien, jusqu'à ce que je compris que toute la classe Player
exécutait maintenant dans l'EDT. Alors, quand j'attends des commandes à partir du serveur les verrous entiers GUI jusqu'à cette commande est envoyée et les actions appropriées sont exécutées. Comme vous pouvez l'imaginer, c'est un horrible dessein et se sont révélés être une vraie douleur d'un environnement de codage lorsque chaque fois que vous voulez vérifier quelque chose que vous devez trouver un travail fou autour de sorte que l'interface graphique reste intacte.
De toute évidence, je dois vérifier les commandes à partir du serveur dans un thread séparé et exécuter les composants de l'interface graphique du EDT. Ma deuxième mise en œuvre avait deux classes - une pour l'interface graphique et un pour le Player
. L'idée était que la Player
avait une variable qui a tenu l'interface graphique pour que je puisse accéder à l'interface de la classe Player
, quelque chose comme ceci:
class Player
{
public GUI gui;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
this.gui = new GUI().setVisible(true);
}
}
Cela ne fonctionne pas non plus, parce que this
intérieur du nouvel objet Runnable
fait référence à l'objet Runnable
, pas le Player
.
Comment puis-je communiquer entre la classe Player
dans un thread et la classe GUI correspondante dans le fil EDT?
La solution
Autres conseils
Pour gérer votre problème avec le pointeur de this
, vous devez écrire:
class Player
{
public GUI gui;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Playser.this.gui = new GUI().setVisible(true);
}
}
}
Boris Pavlović obtient le droit de syntaxe (en fait, vous pouvez simplement supprimer le this.
), mais le code n'a pas de sens. Le champ gui
est initialisée quelque temps après l'événement Runnable
est mis en attente, il est dangereux pour le fil de joueur à utiliser.
Vous pouvez construire Player
sur l'EDT (mais pas les opérations de réseau hors HAE). Ou enregistrez-vous l'interface graphique en tant qu'auditeur (observateur) du Player
. invokeAndWait
fonctionnerait, mais est dangereuse car elle conduit souvent à l'impasse difficile à debug occasionnel.
Vous pouvez essayer ceci:
joueur de classe { GUI publique IUG;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Player.this.gui = new GUI().setVisible(true);
}
}
« jusqu'à ce que je compris que l'ensemble de la classe du joueur exécutait maintenant dans le EDT »
Le constructeur se produit sur l'EDT mais les méthodes dites de cette classe pourrait ne pas être.
Vous devez construire l'interface graphique du lecteur comme vous le souhaitez à l'origine.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
Mais joueur peut lancer un thread séparé dans le constructeur (personnellement, je partage un lien entre les joueurs).
Bien sûr, devraient utiliser invokeLater les méthodes de rappel à partir du serveur () lors de la modification des composants visibles.
Au lieu d'utiliser une classe interne anonyme, pourquoi ne pas simplement déclarer une classe les outils Runnable et un constructeur qui prend une instance GUI comme argument?
En outre, si votre classe GUI est pas sûre, pensez à utiliser une file d'attente de messages pour communiquer entre le fil DETC principal.