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

Langage Delphi Discussion :

Programmation Multi Threads


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Par défaut Programmation Multi Threads
    Bonjour,

    Je me heurte a un petit problème gênant dans une application multi thread.

    Voici un résumé succinct de ce que l'application est sensée faire :
    1. Lorsque l'utilisateur appuie sur le bouton Start:
    - Un répertoire prédéfini sera monitoré via la classe TDirectoryMonitor (http://www.osnews.com/story/7376/A_D..._Delphi/page1/) et dès qu'une image .tif est ajoutée, un traitement sera effectué sur cette image. (Cf. point 2) Nous appellerons ce répertoire le répertoire INPUT
    - Un répertoire prédéfini sera monitoré via la même classe et dès qu'un fichier .txt est ajouté, un traitement sur ce fichier texte sera effectué. Nous appellerons ce répertoire le répertoire OUTPUT.
    2. Le traitement de l'image se fait via le lancement d'une application en ligne de commande (Via CreateProcess et les info trouvées ici : http://www.developpez.net/forums/d39...uperer-retour/) Les info retournées sur la console par l'application en ligne de commande sont sauvegardées dans un fichier de log. (Contrôlé par une sémaphore) L'application en ligne de commande génère un fichier texte qui sera sauvé dans le répertoire OUTPUT.

    Voici au niveau code comment est structurée l'application :
    FMain (Formulaire principal) lance FMonitoringIput, FMonitoringOutput et FReadConsoleOuput, qui sont tous les 3 des threads.

    Les deux premiers tournent sans problème et réagissent correctement à l'ajout de fichiers. Le problème vient de FReadConsoleOutput. J'ai tenté de le lancer à partir de FMonitoringInput (L'application en ligne de commande se lance lorsqu'il y a un fichier image .tif qui arrive dans INPUT) mais son lancement bloque l'arrivée des messages venant de l'ajout d'un fichier dans INPUT. (Donc si j'ajoute un fichier dans INPUT puis un autre avant que l'application en ligne de commande n'ait fini sont traitement, le message semble perdu et le fichier n'est pas traité)

    J'ai tenté de Mettre FReadConsoleOutput dans FMain et de créer un Stack (Thread Safe) où je push mes infos pour le lancement de l'application en ligne de commande mais ça bloque dès le lancement du thread FReadConsoleOuput qui ne veut pas rendre la main à FMain.

    J'aimerais savoir comment faire pour gérer ce cas de figure, soit, en plus simple :
    App => Thread1 => Thread3 (Tout en permettant à Thread1 de continuer à recevoir des messages et stacker les infos pour le lancement de Thread3 séquentiellement)
    App => Thread2

    J'espère avoir été clair, sinon, n'hésitez pas à demander plus d'info... je bloque vraiment sur ce coup-là et le Delphi est loin d'être mon langage de prédilection.

    Merci d'avance,

    S.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Par défaut
    En fait, en C#, j'ai la solution pour gérer ce problème =>
    Je crée une Fonction FileAdded qui est appelée lors de l'ajout d'un fichier puis je crée le process pour l'application en ligne de commande et le stocke dans une ProducerConsumerQueue via la méthode EnqueueTask(process) mais je ne vois pas comment simuler ça en Delphi.

    Si quelqu'un peut m'aiguiller, ça serait magnifique.

  3. #3
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    si j'ai bien compris, tu as 2 thread pour monitorer INPUT et OUTPUT...un événement se déclenche quand un fichier tombe dans un des répertoire...et je suppose que tu es là dans le Thread Principal...il faut donc lancer un Thread secondaire pour executer ton programme en ligne de commande pour que le moniteur reprenne son travail.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Par défaut
    Ca ressemble à ça, oui...

    En fait, j'ai testé plusieurs solutions :
    1. Mon programme principal lance 3 threads:
    - Monitoring INPUT (Si ajout fichier, ajout d'un appel sur le stack)
    - Monitoring OUTPUT
    - Lecture du stack pour lancer l'application en ligne de commande et lire l'output de la console.

    => L'application bloque au lancement du thread de lecture du stack, il ne rend pas la main au programme principal.

    2. Mon programme principal lance 2 threads:
    - Monitoring INPUT => Si ajout => Lance 1 thread qui lance l'application en ligne de commande et lit l'output de la console
    - Monitoring OUTPUT

    => Monitoring INPUT reste bloqué tant que l'application en ligne de commande n'a pas terminé et ce monitoring ne reçoit plus de message, donc l'ajout de fichiers dans le répertoire pendant ce traitement est ignoré.

    Aucune des deux solution ne semble fonctionner comme je veux.

  5. #5
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    le problème doit être dans ton code car le propre d'un thread secondaire est de ne pas bloquer le code qui le lance
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Par défaut
    Voilà mon code, pour info:

    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
     
    procedure TReadConsoleThread.CaptureConsoleOutput(ConsoleApp : string);
    const
    	ReadBuffer = 2400;
    var
      SEInfo : TShellExecuteInfo;
      ExitCode : DWORD;
    begin
      WaitForSingleObject(FSemaphoreLog, INFINITE);
      Log('Before Wait In Thread ID ' + IntToStr(Self.ThreadID) + ' - SEM : ' + IntToStr(FSemaphoreRead));
      ReleaseSemaphore(FSemaphoreLog, 1, nil);
      WaitForSingleObject(FSemaphoreRead, INFINITE);
      FillChar(SEInfo, SizeOf(SEInfo), 0);
      SEInfo.cbSize := SizeOf(TShellExecuteInfo);
      With SEInfo Do
      begin
        fMask := SEE_MASK_NOCLOSEPROCESS;
        Wnd := Application.Handle;
        lpFile := PChar(AppPath);
        lpParameters := PChar(Args);
        nShow := SW_SHOWNORMAL;
      end;
      if ShellExecuteEx(@SEInfo) then
      begin
        repeat
          Application.ProcessMessages;
          GetExitCodeProcess(SEInfo.hProcess, ExitCode);
          Log('Exit Code : ' + IntToStr(ExitCode));
        until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
        WaitForSingleObject(FSemaphoreLog, INFINITE);
        Log('After Processing In Thread ID ' + IntToStr(Self.ThreadID));
        ReleaseSemaphore(FSemaphoreLog, 1, nil);
        ReleaseSemaphore(FSemaphoreRead, 1, nil);
        WaitForSingleObject(FSemaphoreLog, INFINITE);
        ReleaseSemaphore(FSemaphoreLog, 1, nil);
      end;
    end;
    Et ça bloque sur la ligne Application.ProcessMessage. Il process bien les message mais avec la Semaphore FSemaphoreRead, il ne la libère jamais donc ça bloque.

    Une idée?

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

Discussions similaires

  1. Programmation multi-Threads en R sur windows
    Par boris150 dans le forum R
    Réponses: 2
    Dernier message: 12/03/2014, 15h25
  2. [BP7] Multi-cpu, multi-core, multi-thread et programme Pascal
    Par Transgarp dans le forum Turbo Pascal
    Réponses: 6
    Dernier message: 07/04/2008, 18h43
  3. Réponses: 3
    Dernier message: 25/04/2007, 13h21
  4. Programmation Multi-threadée et Synchronisme
    Par ChPortos dans le forum Windows Forms
    Réponses: 2
    Dernier message: 18/04/2007, 11h59
  5. Réponses: 11
    Dernier message: 14/02/2006, 00h26

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