IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

Problème de threads


Sujet :

JavaFX

  1. #1
    Invité
    Invité(e)
    Par défaut Problème de threads
    Bonjour,

    J'ai un petit script JavaFX qui, lorsqu'il est lancé, se met en attente d'un évènement réseau par le biais d'une méthode bloquante Java.
    Le problème est que j'aimerais dans le même temps afficher un Stage.

    J'en conclu qu'il faut que la partie réseau tourne dans un thread séparé de celui du Stage.
    J'ai essayé d'utiliser la classe Thread de Java, mais un message d'erreur m'annonce : "explicit use of threads is not supported".
    Comment faire ?

    Merci d'avance.

    Axel

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    32
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 32
    Par défaut
    Bonjour,
    la création de Thread de cette manière n'est pas (plus) supportée par JavaFX.
    Par contre, tu peux créer une tâche qui implémente Runnable dans laquelle tu effectues ton traitement à l'aide de FX.deferAction().

    Voici un petit bout de code qui pourrait t'éclairer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    def pool : ExecutorService = Executors.newCachedThreadPool();
     
    public class MultiThreading {
        public var str: String = "string";
    }
     
    function process(multi: MultiThreading) {
        var s = multi.str;
        var task: Runnable = Runnable {
            override function run() {
                s = "{s}->modifiée par un Thread";
                FX.deferAction(function(): Void { multi.str = s });
            }
        }
        pool.execute(task);
    }
     
    function run() {
        var multi = MultiThreading{};
        Stage {
            title : "MyApp"
            scene: Scene {
                width: 200 height: 200
                content: VBox {
                    spacing: 20
                    content: [
                        Button {
                            font : Font { size: 16 }
                            text: "Illustration du multithread"
                            action: function() { process(multi) }
                        }
                        Text {
                            wrappingWidth: 200
                            font : Font { size: 16 }
                            textOrigin: TextOrigin.TOP
                            content: bind multi.str
                        }
                    ]
                }
            }
        }
    }
    Peace.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Merci pour ta réponse.

    Dans mon script, la tâche a une durée théoriquement infinie : tant que le socket réseau est ouvert, la boucle while continue à être traversée afin de détecter la réception éventuelle de données sur le flux d'entrée.

    J'ai écrit le code ci-dessous, mais il ne fonctionne pas : tant que le socket est ouvert, la fenêtre du script est bloquée (impossible à fermer).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def pool : ExecutorService = Executors.newCachedThreadPool();
     
    Stage {
        title: "Titre"
        width: 800
        height: 600
        scene: Scene {
        }
    }
     
    var task: Runnable = Runnable {
        override function run() {
            var serverConnection: ServerConnection = ServerConnection{};
            FX.deferAction(function() {
                //Lancement de la boucle while
                serverConnection.openConnection("localhost", client)
            });
        }
    }
     
    pool.execute(task);
    Saurais-tu d'où vient le problème ?

    Merci.
    Axel

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 64
    Par défaut
    Sauf erreur de ma part (j'ai pas encore joué avec le multithread en JavaFX), je pense que tu dois lancer ta boucle infinie dans la function run(), c'est elle qui tourne dans le thread. Le FX.deferAction sert à mettre à jour le GUI, un peu comme l'invokeLater de Swing.

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 904
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 904
    Billets dans le blog
    54
    Par défaut
    Exact, il faut utiliser JavaTaskBase pour les choses sensées s'exécuter dans une autre thread. Egalement dans JavaFX 1.1.1 j'avais pu utiliser SwingWorker sans problème.

    Voir :
    http://blogs.sun.com/clarkeman/entry/javafx_async_task
    http://jfxstudio.wordpress.com/2009/...ons-in-javafx/
    http://blogs.sun.com/baechul/entry/javafx_1_2_async
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Février 2009
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 284
    Par défaut
    Même si cela n'est pas documenté correctement, le runtime javaFX est composé d'une multitude de pools de threads, dans l'api il y en a un qui est dédié au tâches de fond. Sinon pour utiliser des choses similaires à l'exemple de PhiLho, un executor maison ne pose pas de problèmes (impossible d'utiliser un simple thread).
    Il faudra juste prendre garde à ce que les objets manipulés dans le Runnable ne soient pas bindés à l'UI ou à ne pas modifier le SceneGraph via le Runnable (FX.deferAction est la pour la). Il faut d'ailleurs faire attention à tout ce que l'on fait avec les variables car le langage en lui même est permissif quand à l'accessibilité de celles ci dans le code, contrairement à java, ou l'on doit utiliser le plus souvent des objets finaux dans les Threads, dans javaFx les choses sont moins strictes. Je te conseille donc plus d'utiliser une librairie java à part pour du code sensible.
    Et puis dernière petite chose, toujours travailler avec le profiler.

  7. #7
    Invité
    Invité(e)
    Par défaut
    OK j'ai compris le principe. Mais ça ne fonctionne toujours pas...
    Mon problème est que je ne vois pas trop comment mettre à jour (et initialiser par la même occasion) le GUI. Parce qu'en début de script, c'est facile il suffit de mettre Stage{}, mais depuis un deferAction()...

    Voici quelques bouts de code :

    Script principal Client Test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function run() {
        var client = ClientTest {
            serverConnection: ServerConnection{};
        }
        client.serverConnection.openConnection("localhost", client);
    }
     
    public class ClientTest {
        public var serverConnection: ServerConnection;
    }
    Classe ServerConnection qui est censée lancer la boucle while dans laquelle se trouve un deferAction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class ServerConnection {
        var  client: Client;
        var  socket: Socket;
        var  protocol: ClientToServerProtocol;
     
        public function openConnection(address: String, client: ClientTest) {
            this.client = client;
            socket = new Socket(address, PORT);
            protocol = ClientToServerProtocol {};
            protocol.initProtocol(socket);
            println("[Server Connection] Socket Opened");
     
            def pool : ExecutorService = Executors.newCachedThreadPool();
            var task: Runnable = Runnable {
                override function run() {
                    while(socket.isConnected()) {
                        protocol.processRequest(client);
                        FX.deferAction(function() {
                            [....]
                        });
                    }
                }
            }
            pool.execute(task);
        }
    }
    Note : La fonction processRequest de la classe ClientToServerProtocol rend la main tant qu'il n'y a pas de données sur le flux d'entrée.

    Donc en résumé, la fonction run instancie la classe ClientTest et lui affecte une nouvelle instance de ServerConnection, puis ouvre la connexion.
    Une fois la connexion initialisée, la boucle while est lancée dans une tâche du pool ExecutorService.
    Mais c'est ici que je bloque, comment faire pour demander au client, depuis la fonction deferAction(), d'afficher un Stage et de le mettre à jour continuellement ?

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Février 2009
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 284
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    //dans le Runnable avant la boucle 
    var stage=null;
    //dans la boucle sur réception
    FX.defer.. {
        if(stage == null) {
            stage = Stage {
                 //dès que tu icrée un stage dans l'EDT il s"affiche
                  ...
            }
            stage.scene.content = Label { 
                text: "moninfoquejeveuxafficherdanslestage"
             } 
        }
    }

  9. #9
    Invité
    Invité(e)
    Par défaut
    Cool ça marche !
    Merci beaucoup

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de thread : Plus de ressources système
    Par OliverSleep dans le forum C++Builder
    Réponses: 17
    Dernier message: 07/02/2006, 15h35
  2. [VB.NET] Problème de Thread
    Par Sadneth dans le forum ASP.NET
    Réponses: 26
    Dernier message: 31/01/2006, 10h12
  3. Problème synchronisation threads
    Par Linio dans le forum Concurrence et multi-thread
    Réponses: 19
    Dernier message: 11/01/2006, 16h57
  4. [MFC] Problème de Threads + Timers
    Par Invité dans le forum MFC
    Réponses: 8
    Dernier message: 30/11/2005, 10h51
  5. [VC++6][DX9] Problème de thread lors d'un blit ...
    Par grandjouff dans le forum DirectX
    Réponses: 2
    Dernier message: 12/06/2003, 22h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo