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

WinDev Discussion :

[WD8] Gestion d'une table depuis deux threads différents


Sujet :

WinDev

  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    927
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 927
    Points : 2 113
    Points
    2 113
    Par défaut [WD8] Gestion d'une table depuis deux threads différents
    Bonjour,

    Je travail sur une machine qui a 254MB de mémoire et 630Mhz de puissance CPU. C'est pas super, mais c'est suffisant pour faire du windev.

    Je fais des tests avec les threads et j'ai un petit problème.
    J'ai une table.
    Avec un premier thread je la remplit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Procédure exécutée par le premier thread
    BOUCLE
    	SI i > 5000 ALORS
    		SORTIR // pour ne pas avoir l'erreur de compilation
    	FIN
                 // on ajoute une ligne à la table
    	TableAjoute(TableTest, "Nom" + i + TAB + "Prenom" + i) 
                 // on ouvre le signal : le thread 2 va reprendre son exécution (voir plus loin)
    	SignalModifie(NomSignal, signalOuvert)
    	i++
    FIN
    (Le code de création du signal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    NomSignal est une chaîne = "Signal1" 
    SignalCrée(NomSignal, signalManuel, signalFermé)
    )

    Avec un second thread, je vide la table :

    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
    // code exécuté par le deuxième thread
    
    idFichier est un entier = fOuvre("C:\Mes Projets\Tests\Exe\lu.txt", foCréationSiInexistant)
    fPositionne(idFichier, 0, fpFin)
    
    BOUCLE
    	// si la table est vide
    	SI TableOccurrence(TableTest) = 0 ALORS
                              // on ferme le signal
    		SignalModifie(NomSignal, signalFermé)
                              // on attend que le signal soit ouvert (que la table se remplisse)
    		SignalAttend(NomSignal)
    	FIN
    
                 // on écrit la ligne de la table dans un fichier
    	fEcritLigne(idFichier, TableTest[1][1]+TableTest[1][2])	
                // on supprime la ligne de la table
                TableSupprime(TableTest, 1)	
                // on ferme le signal
    	SignalModifie(NomSignal, signalFermé)
    	
    	SI L_TableTest = "yoluhou" ALORS
    		SORTIR // pour ne pas avoir l'erreur...
    	FIN
    		
    FIN
    Le problème est à la ligne en rouge. Mais c'est pas vraiment là que se situe le problème, en fait, cette ligne en rouge m'a montrer qu'il y a une faille dans le code.

    L'erreur :
    Erreur à la ligne 36 du traitement Procédure locale ProcedureThread2.
    La liste est vide.
    Aucun indice n'est valide pour le champ TableTest.
    (Indice spécifié : 1).
    Ca veut dire que dans le thread 2, après être sortit de la fonction SignalAttend(), le tableau est toujours vide. Or c'est impossible vu que s'il on est sortit de cette fonction (SignalAttend()) c'est que le thread 1 vient d'ajouter un enregistrement dans la table.

    Je sais que c'est plus compliqué que ça, ça se joue à la micro-seconde... Et en mettant la ligne ThreadAttendSignal(100) juste après la fonction SignalAttend() du thread 2, ça fait l'erreur moins facilement.

    Est-ce que je devrais pouvoir trouver une manière de résoudre ce problème en faisant un diagramme de séquence?
    Merci de me dire ce que vous en pensez.
    "If you can't teach it then you don't know it."

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 724
    Points
    5 724
    Par défaut
    Qu'est-ce que tu cherches à réaliser ?

    Le thread1 écrit une ligne dans la table et attends que le thread2 la stocke dans un fichier, une fois que le thread2 termine son enregistrement alors le thread1 supprime la ligne et en réecrit une autre, et ainsi de suite ?
    " Dis ce que tu veux qui insulte mon honneur car mon silence sera la réponse au mesquin.
    Je ne manque pas de réponse mais : il ne convient pas aux lions de répondre aux chiens ! " [Ash-Shafi'i ]

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    927
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 927
    Points : 2 113
    Points
    2 113
    Par défaut
    Non en fait j'aimerais que le thread 1 remplisse la table, à son rythme indépendement du thread 2. Il faudrait que le thread 2 s'arrète quand la table est vide et qu'il redémarre dès qu'il peut (dès que le thread 1 ajoute de nouvelles lignes dans la table) et non pas avoir cette chronologie : ajout puis suppression.

    En fait c'est pour gagner du temps, faire la lecture (ce sera une lecture dans une table) dans un thread et faire le traitement (ecriture dans une table) dans un autre thread.
    "If you can't teach it then you don't know it."

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 724
    Points
    5 724
    Par défaut
    Qui est chargé de la suppression d'une ligne de la table le thread1 ou le thread2 ?
    " Dis ce que tu veux qui insulte mon honneur car mon silence sera la réponse au mesquin.
    Je ne manque pas de réponse mais : il ne convient pas aux lions de répondre aux chiens ! " [Ash-Shafi'i ]

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    927
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 927
    Points : 2 113
    Points
    2 113
    Par défaut
    C'est le thread 2 qui se charge de supprimer les lignes de la table.
    "If you can't teach it then you don't know it."

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    19 647
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 19 647
    Points : 32 889
    Points
    32 889
    Par défaut
    À mon avis, tu dois suspendre l'exécution du Thraed "concurrent" avec les fonctions ThreadSuspend() & ThreadReprend ()

    Tu peux aussi utiliser :
    - les Sémaphores (Thread, Sémaphore)
    Les sémaphores permettent de limiter l'exécution simultanée d'un code (procédure, ligne de code, ...) à un ou plusieurs threads à un instant donné.
    - les Signaux (Thread, Signal) pour communiquer entre Threads
    Les signaux permettent de synchroniser les différents threads d'une application. Un thread peut ainsi attendre l'exécution d'un autre thread.

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    927
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 927
    Points : 2 113
    Points
    2 113
    Par défaut
    Citation Envoyé par Guardian
    À mon avis, tu dois suspendre l'exécution du Thraed "concurrent" avec les fonctions ThreadSuspend() & ThreadReprend ()
    Le thread concurrent du thread 1 est le thread 2 et inversément? Le problème c'est que ça ne fera pas l'ajout et la suppression en même temps.

    Je précise une chose, les threads devront plus tard effectuer ces tâches :
    - thread 1 lit les enregistrements d'une table et en fonction de la valeur d'une rubrique envoit l'enregistrement au thread 2 ou pas.
    - thread 2 effectuera un même traitement pour chaque ligne : analyse de la ligne etc. Ce traitement sera assez long et empechera le thread 1 de continuer à rechercher des lignes "intéressantes".

    J'ai pensé aux threads pour ceci : le thread 1 aura bcp de lignes à parcourir pour trouver les enregistrements "intéressants". Et donc dès qu'il en trouve un, on demande à un autre thread de l'analyser pendant que le thread 1 continue sa recherche... Je me dis que ça améliorera les performances car faire la recherche (thread 1) risque de ne pas prendre beaucoup de ressources CPU et donc on peut faire quelque chose en même temps.

    Si je parvenais à localiser précisément le problème...

    Il faudrait que je protège l'accès à la table par des sémaphores? Pour pouvoir partager une zone mémoire il le faut, mais je ne comprends pas pourquoi c'est utile ici. Le thread 2 vérifie qu'il y a au moins une ligne dans la table. Entre le temps où l'on fait la vérification (SI TableOccu...) et le temps où l'on supprime la ligne de la table, comment est-il possible qu'il n'y ai plus de ligne? Il n'y a que le thread 2 qui supprime des lignes de la table.


    Citation Envoyé par goomazio
    En fait c'est pour gagner du temps, faire la lecture (ce sera une lecture dans une table) dans un thread et faire le traitement (ecriture dans une table) dans un autre thread.
    Durées approximatives d'exécution (thread 1 ajoute 1000 ou 10000 lignes dans la table et thread 2 les supprimes):
    Thread 1 puis thread 2 :
    - 1000 lignes : 30 sec
    - 10000 lignes : 1 min 29 sec
    Thread 1 et thread 2 en même temps :
    - 1000 lignes : entre 20 et 23 sec
    - 10000 lignes : 1 - 2 - 3 min (assez variable en fait)
    Code thread 1 et code thread 2 sans thread (dans le thread principal) :
    - 1000 lignes : 4 sec
    - 10000 lignes :42 sec
    Ce n'est pas des moyennes, je n'ai faus les calculs que quelques fois.

    Donc c'est inutile dans mon cas d'utiliser des threads. Est-ce qu'avec des traitements plus lourds, ce sera utile?


    En passant, nouveau code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    PROCEDURE ProcedureThread1()
    i est un entier = 1
    TANTQUE i < 10000
    	// Ajout d'un enregistrement dans la table
    	TableAjoute(TableTest, "Edouard" + i + TAB + "Batolo" + i)
    	// On ouvre le signal
    	SignalModifie(NomSignal, signalOuvert)	
    	i++
    FIN
    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
    PROCEDURE ProcedureThread2()
    idFichier est un entier = fOuvre("C:\Mes Projets\Tests\Exe\lu.txt", foCréationSiInexistant)
    fPositionne(idFichier, 0, fpFin)
    TANTQUE Vrai
    	// Si la table est vide on attend
    	SI TableOccurrence(TableTest) = 0 ALORS
    		// On ferme le signal
    		SignalModifie(NomSignal, signalFermé)
    		// On attend que le signal soit ouvert (que la table se remplisse)
    		SignalAttend(NomSignal)
    	SINON
    		// On écrit la première ligne de la table dans un fichier
    		fEcritLigne(idFichier, TableTest[1][1]+TableTest[1][2])
    		// On supprime la première ligne de la table
    		TableSupprime(TableTest, 1)	
    		// On ferme le signal
    		SignalModifie(NomSignal, signalFermé)
    	FIN
    FIN
    Merci pour vos réponses,
    Les threads ce n'est pas si simple que ça (ça me rappelle un autre post...)
    "If you can't teach it then you don't know it."

Discussions similaires

  1. Réponses: 3
    Dernier message: 18/04/2008, 14h28
  2. Une table ou deux - quel est le meilleur choix
    Par DG dans le forum Débuter
    Réponses: 3
    Dernier message: 09/03/2006, 18h04
  3. [SQL] couper une table en deux
    Par irenee dans le forum Langage SQL
    Réponses: 4
    Dernier message: 05/03/2006, 14h59
  4. comment filtrer une table avec deux criteres càd 2 colonnes
    Par athmane2dz dans le forum Bases de données
    Réponses: 7
    Dernier message: 28/07/2004, 15h25
  5. Mettre à jour une table depuis une autre
    Par rsc dans le forum SQL
    Réponses: 4
    Dernier message: 09/07/2004, 10h08

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