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

C++Builder Discussion :

Accès à Word dans un thread


Sujet :

C++Builder

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 40
    Points : 38
    Points
    38
    Par défaut Accès à Word dans un thread
    Bonjour,
    Afin de proposer aux utilisateurs un bouton Arrêter l'impression, j'ai créé un Thread, le programme principal est une DLL.
    Ce thread lance une procédure (fonctionnant parfaitement dans le contexte du programme principal) qui plante : Indice de liste hors limite(2). Cette erreur ne semble pas concerné le thread puisqu'il continue à fonctionner jusqu'au bout sans erreur.

    La procédure utilise une liste de signets Word (j'ai initialisé cette liste avec ThreadList), ouvre Word et accède à la base de données via BDE pour renseigner les signets d'un modèle de document.

    Voici le code :
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    Initialisations:
      TList *signetsWord=new TList();
      threadsignetsWord=new TThreadList();
      threadsignetsWord->Add(signetsWord);
      signetsWord=threadsignetsWord->LockList();
    
      TfImprime *fImprime=new TfImprime(Screen->Forms[0]);
      fImprime->Threaded=true;
      fImprime->typeModele=typeModele;
      fImprime->statut_bonlabo=statut_bonlabo;
      fImprime->statut_dialyse=statut_dialyse;
      fImprime->ShowModal();
    
    Lancement du thread à partir de la fenêtre fImprime :
    void __fastcall TfImprime::btAnnuleClick(TObject *Sender)
    {
       Suspended=true;
       btAnnule->Enabled=false;
       if (Threaded)
          ThreadImp->Terminate();
    }
    //---------------------------------------------------------------------------
    void __fastcall TfImprime::Termine(TObject *Sender) {
       delete ThreadImp;
       Close();
    }
    //---------------------------------------------------------------------------
    void __fastcall TfImprime::Timer1Timer(TObject *Sender)
    {
       Timer1->Enabled=false;
       if (Threaded) {
          ThreadImp=new TThreadExe(true);
          ThreadImp->typeModele=typeModele;
          ThreadImp->statut_bonlabo=statut_bonlabo;
          ThreadImp->statut_dialyse=statut_dialyse;
          ThreadImp->Priority=tpNormal;
          ThreadImp->FreeOnTerminate=false;
          ThreadImp->OnTerminate=Termine;
          ThreadImp->Resume();
       }
    }
    //---------------------------------------------------------------------------
    void __fastcall TfImprime::FormShow(TObject *Sender)
    {
       Timer1->Enabled=true; // oui le timer n'est pas utile....
    }
    //---------------------------------------------------------------------------
    
    Voici la classe TThread :
    
    //---------------------------------------------------------------------------
    __fastcall TThreadExe::TThreadExe (bool CreateSuspended):TThread(CreateSuspended){
    }
    //---------------------------------------------------------------------------
    void __fastcall TThreadExe::Execute(){
       CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
       Lance();
       CoUninitialize();
    }
    //---------------------------------------------------------------------------
    void __fastcall TThreadExe::Lance(void) {
       TSignet::Word->printBoucle(typeModele,statut_bonlabo,statut_dialyse);
    }
    //---------------------------------------------------------------------------
    
    Le code de recherche des signets :
    
      for(int i=0; i<signetsWord->Count; i++){
        unSignet=(TSignet *)signetsWord->Items[i];
        ....<suite du code>...
    tous les try catch que j'ai pu mettre sont sans effet même au niveau de l'exe.
    Quelqu'un aurait-il une idée d'où vient l'erreur ?
    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 429
    Points : 24 794
    Points
    24 794
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TList *signetsWord=new TList();
      threadsignetsWord=new TThreadList();
      threadsignetsWord->Add(signetsWord);
      signetsWord=threadsignetsWord->LockList();
    Ce code est très étrange et difficilement maintenable, tu instancies un TList, tu devrais mettre un commentaire au sujet de sa libération ou alors tu n'as pas compris le fonctionement de LockList

    Tu ajoute une liste dans la liste ???
    Pourquoi ne pas ajouter tes TSignet directement dans la TThreadList ?
    Est-ce un arbre ???

    signetsWord tu lui affecte la liste dévérouillée, la même variable pour deux utilisation différentes ???
    Que c'est vilain !

    Il ne faut pas faire un LockList trop long, il faut qu'il soit le plus court que possible
    Est-ce des variables globales ?
    Si oui, c'est moche, encapsule tout cela (thread+list), dans un objet que tu instancie au moment voulu, appliqué du RAII serait parfait pour cela
    Si non, difficile de comprendre ton code, certains effets de bords sont peut-être lié à ton archi de code

    ton code devait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      threadsignetsWord = new TThreadList(); 
      threadsignetsWord ->Duplicates = dupAccept;
     
      while ( ! DataSet->EOF )
      {
        TSignet *unSignet = new TSignet();
        unSignet->LoadFromDataSet(DataSet);
        threadsignetsWord->Add(unSignet); // Ajoute thread-safe
     
        DataSet->Next();
      }
    puis vérouille juste avant la boucle, pour éviter un dead lock si exception, il est prudent de systématisé UnlockList

    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
    ...
      TList* lst = threadsignetsWord->LockList(); 
      try
      {
        for(int i=0; i<lst->Count; i++)
        {
          TSignet *unSignet = reinterpret_cast<TSignet*>(lst->Items[i]);
          ....<suite du code>..
        }
      }
      __finally
      {
         threadsignetsWord->UnlockList();
      }
    ...
    Sinon la TThreadList n'a de pertinence que si tu prévois un ajout en parallèle du parcours, vu la structure de ton code, cela ne semble pas du tout le cas, tu aurais pu faire une TList interne au TThreadExe et une méthode Add ou AddList
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 40
    Points : 38
    Points
    38
    Par défaut
    Bonjour ShaiLeTroll et merci de ta réponse. Effectivement au vue des propositions que tu fais,je n'ai rien compris au Threadlist.
    Un grand merci, et je revois mon code (initialisement prévu pour travailler sans interruption d'où les incohérences).

Discussions similaires

  1. Accès à DocumentProperties dans Word ?
    Par PSA78 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 01/11/2010, 16h42
  2. Comment lancer Word dans un thread séparé
    Par Tony49 dans le forum C++Builder
    Réponses: 3
    Dernier message: 22/03/2009, 13h43
  3. [Struts][Oracle]Upload fichier word dans une base
    Par Maximil ian dans le forum Struts 1
    Réponses: 7
    Dernier message: 10/02/2004, 16h52
  4. [tomcat]acces fichier dans contexte
    Par krollette dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 23/01/2004, 15h17
  5. Gestion des message windows dans les threads
    Par billyboy dans le forum Windows
    Réponses: 5
    Dernier message: 06/10/2003, 18h25

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