begin process at 2008 08 20 14:30:04
1 228 866 membres
232 nouveaux aujourd'hui
14 257 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : Probleme fermeture de Thread!!! [ Windows / System ] (Dryko)

Probleme fermeture de Thread!!! le 11/06/2008 11:00:50

Dryko
Bonjour,

Je suis en train de programmer une application MFC dans lequel je créer un thread (avec CreateThread) dans le constructeur de ma classe.
Dans le destructeur de ma classe, je detruit (enfin j'essaye c'est la mon probleme) le thread avec TerminateThread.

Mon application marche parfaitement mais lorsque je la ferme, j'ai un gros message d'erreur "L'instruction à "0x00b1234" emploie l'adresse mémoire "0x00b1234". La mémoire ne peut être "read""......... :(

Apres un nombre incalculable de test, j'ai compris que cela venais de la destruction du thread (je ne pense pas que cela vienne de la creation vu qu'il marche tres bien) car si je ne le créé pas, je n'ai pas de pb et si je le créé et que je met seulement une boucle while infinie ca plante!!!...
J'ai beau avoir essayer toute les configurations de fermeture de thread telles :
terminatethread
exit thread
closehandle
getexitcodethread
.....
J'ai essayé tout ca dans tout les sens : tjours la meme erreur!!!!!!

Aidez moi je vous en supplie je vais craquer!!!!!

Merrci d'avance

Re : Probleme fermeture de Thread!!! le 11/06/2008 11:50:31

BruNews
(Admin CS)
TerminateThread est à proscrire en utilisation normale, c'est une fonction d'urgence à n'employer que ponctuellement.

CreateThread est à remplacer par les fonctions MFC.

ciao...
BruNews, MVP VC++

Re : Probleme fermeture de Thread!!! le 12/06/2008 11:08:26

pipocodesrc

J'utilise le truc plus bas sans aucun soucis dans une classe perso.
hope this help

class Thread
{
private:
  HANDLE  _handle;
  dword      _idth;
  bool        _created,                       // true is create succesfully
                _exitmainloop;               // used in MainLoop
                _exitthread;
  int         _term_nbtry,_term_wait;  // used for Stop

public:

Thread()
{
_handle   =null;
_created=false;
_exitmainloop=false;
_exitthread=false;
}

bool Create()
{
  _handle = (HANDLE) __beginthreadex       
        (&Thread::STATIC_MainLoop,
         4096,                                // Thread stack size
         this,                                 // Thread start argument
         0,//&sa,                            // Thread security
         CREATE_SUSPENDED,   // Create in suspended state
         &_idth);                            // Thread ID.
 _created=_handle!=INVALID_HANDLE_VALUE;
return _created;
}

//main process
MainLoop()
{
 _exitmainloop=false;
  if (_created) while (!ExitLoop())  { cout<<'.'; Sleep(100); }
 _exitmainloop=true;
 _endthreadex(0);
}

inline bool ExitLoop() { return _exitthread; }

inline bool Created() { return _created; }
inline dword Start () {  return  ResumeThread(_handle); } // fails  if == 0xFFFFFFFF otherwise succeed
inline dword Pause () {  return SuspendThread(_handle);  } // fails  if == 0xFFFFFFFF otherwise succeed
bool Stop (dword ms=250,word nbretry=40)
{
  _term_nbtry=0;
  _term_wait =ms;
  _exitthread=true;           // if stopped when I restart the exitloop returns true

  bool  ok=false;
  dword thstatus;

  if (!_exitmainloop) 
  do
  {
   _waitstatus=WaitForSingleObject (_handle, ms);
   switch (_waitstatus)
    {
    case WAIT_ABANDONED : ok=true; break;
    case WAIT_TIMEOUT   :      break;
    case WAIT_OBJECT_0  : ok=true; break;
    case WAIT_FAILED    : ok=true; break;//can happen if handle is invalid  because already stopped
    //default           : ok=true;       // in other case, exit because an error occurs
    }
   if (!ok)
   {
    if (GetExitCodeThread (_handle, &thstatus))
     if (thstatus == STILL_ACTIVE)
     {
      cout<<endl<<" still active"
    }
   }
  }
  while (++_term_nbtry<nbretry && !ok && !_exitmainloop);

  if (!ok || !_exitmainloop) return false;

  CloseHandle(_handle); //must be called when _exitthreadex( rather _exitthread )
  _handle=null;
  _created=false;

  return true;
}

};


Re : Probleme fermeture de Thread!!! le 12/06/2008 11:37:08

Dryko
merci pipoco!
je vais tester dans quelques minutes...
mais dis moi : ton code attend que le thread ai fini de tourner ou le programme principal le tue meme si il a pas fini?..
merci

Re : Probleme fermeture de Thread!!! le 12/06/2008 11:46:03

pipocodesrc

Il attend qu'il est fini de tourner et que le handle soit libéré par un WaitForSingleObject ...
Si tu ne veux pas attendre utilise Terminate... mais mauvais choix si tu restes dans ton appli sinon l'OS se chargera  de gérer.
Si tu reste dans ton appli il faut que tu testes ExitLoop () dans la répétition du while (!ExitLoop()) ..ou ailleurs qui en dépend.

while (!ExitLoop()) ..
{
  code court ... //pas besoin de tests

  code long ...
  if (ExitLoop ()) break;

....

}
..


Re : Probleme fermeture de Thread!!! le 13/06/2008 09:21:29

Dryko
encore merci!

Pour le Terminate je sais que ce n'est pas propre mais mon Thread ne s'arrete jamais, c'est au main de lui dire de s'arreter. C'est pourquoi j'ai adopté une méthode basic : j'ai transformé la boucle infinie du thread en while(stop==false) et c'est le main qui passe le bool à true quand il s'arrete.

Mais En fait je me suis aperçu que le probleme ne venait pas de là... En fait, le programme que je vous ai décrit est un filtre DirectShow. J'utilise ce filtre dans une application MFC dans lequel je créé un graphe DirectShow. Lorsque je ferme l'application, il me detruit bien le graphe mais il ne me "detruit" pas le filtre, donc il ne rentre pas dans le destructeur du filtre et donc ne termine pas le thread.
Je sais pas pourquoi le filtre continue a tourner malgré le graphe soit bien detruit... une ptite idée??...

merci d'avance

Re : Probleme fermeture de Thread!!! le 13/06/2008 09:35:31

pipocodesrc

Salut, qu'est-ce que vous utilisez comme classe de filtre ? car qui dit exit d'application maîtrisée, dit clean de tout l'environnement (stop engine filter ...) donc arrêt de filtre même en train de processer. Vous vous êtes basé sur un sample du sdk ?
...


Re : Probleme fermeture de Thread!!! le 13/06/2008 11:38:16

Dryko

Ben en fait c'est un peu compliqué.... même beaucoup
en fait c'est un filtre que j'ai chopé sur le net :
quand le filtre est créé ca créé une classe qui fait pratiquement que le createinstance et qui lui appelle une autre classe qui fait "tout le travailé".... et je pense que la destruction du filtre detruit la premiere classe mais pas la deuxieme..
voila mon .h, si tu veux jeter un oeil :

#include "freeimage.h"
#include <iostream>
#pragma once

#define DECLARE_PTR(type, ptr, expr) type* ptr = (type*)(expr);

static const GUID CLSID_VirtualCAM;

class CVirtualCamStream;

/**
* @struct thread_param Structure de declaration de thread
* @param cvcs est une classe CVirtualCamStream
* @param soc : socket sur laquelle le programme va recevoir les paquets UDP
*/
struct thread_param{
 CVirtualCamStream* cvcs;
 SOCKET soc;
 MEMOIRE memoire[NOMBRE_MEMOIRE];
};

class CVirtualCam : public CSource
{
public:
    //////////////////////////////////////////////////////////////////////////
    //  IUnknown
    //////////////////////////////////////////////////////////////////////////
    static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
 

    IFilterGraph *GetGraph() {return m_pGraph;}

private:
    CVirtualCam(LPUNKNOWN lpunk, HRESULT *phr);
};

class CVirtualCamStream : public CSourceStream, public IAMStreamConfig, public IKsPropertySet
{
public:
 
 /**
 * Fonctions d'initialisation et de destruction de socket
 */
 SOCKET CVirtualCamStream::SocketInitialise(SOCKET sock);
 void CVirtualCamStream::SocketDeInitialise(SOCKET sock);
 
 /**
 * Fonction de creation de thread qui permet de faire tourner en parallele la fonction de reception des paquets
 */
 static DWORD WINAPI CVirtualCamStream::ThreadReceptionImage(void *p)
 {
  struct thread_param *Obj = reinterpret_cast<struct thread_param*>(p);
  
  CVirtualCamStream *c = Obj->cvcs;
  return c->ReceptionImage(Obj->soc); 
 }

    //////////////////////////////////////////////////////////////////////////
    //  IUnknown
    //////////////////////////////////////////////////////////////////////////
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
    STDMETHODIMP_(ULONG) AddRef() { return GetOwner()->AddRef(); }                                                          \
    STDMETHODIMP_(ULONG) Release() { return GetOwner()->Release(); }

    //////////////////////////////////////////////////////////////////////////
    //  IQualityControl
    //////////////////////////////////////////////////////////////////////////
    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);

    //////////////////////////////////////////////////////////////////////////
    //  IAMStreamConfig
    //////////////////////////////////////////////////////////////////////////
    HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
    HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
    HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
    HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC);

    //////////////////////////////////////////////////////////////////////////
    //  IKsPropertySet
    //////////////////////////////////////////////////////////////////////////
    HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwID, void *pInstanceData, DWORD cbInstanceData, void *pPropData, DWORD cbPropData);
    HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, void *pInstanceData,DWORD cbInstanceData, void *pPropData, DWORD cbPropData, DWORD *pcbReturned);
    HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);

    //////////////////////////////////////////////////////////////////////////
    //  CSourceStream
    //////////////////////////////////////////////////////////////////////////
    CVirtualCamStream(HRESULT *phr, CVirtualCam *pParent, LPCWSTR pPinName);
    ~CVirtualCamStream();

    HRESULT FillBuffer(IMediaSample *pms);
    HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc, ALLOCATOR_PROPERTIES *pProperties);
    HRESULT CheckMediaType(const CMediaType *pMediaType);
    HRESULT GetMediaType(int iPosition, CMediaType *pmt);
    HRESULT SetMediaType(const CMediaType *pmt);
    HRESULT OnThreadCreate(void);
 HRESULT ShutdownThread( );

private:
    CVirtualCam *m_pParent;
    REFERENCE_TIME m_rtLastTime;
    HBITMAP m_hLogoBmp;
    CCritSec m_cSharedState;
    IReferenceClock *m_pClock;
 FILE* pFile;

 /**
 * @param sock correspond à la socket sur laquelle nous communiquons
 * @param WSAData utile pour la création de la socket
 */
 SOCKET sock;
 WSADATA WSAData;
 

 /**
 * Cette fonction doit être déclarée en static car appelée par un thread
 */
 DWORD ReceptionImage(SOCKET sock);

 HANDLE hthread;
 DWORD hthreadId;
 HANDLE m_hShutdownEvent;

 bool stop;
 
};

encore merci de t'interesser a mon cas ;)
 


Re : Probleme fermeture de Thread!!! le 13/06/2008 17:37:31

pipocodesrc

Salut,
Tout destructeur de classe appelle les destructeurs dont il dépend dans l'ordre d'héritage.
Si tu as des classes déclarées et non héritées il faut appeler explicitement celles-ci pour les détruire (sic);
J'ai regardé directshow (en travers), et ai utilisé un sample.
Je pense que cela vient de ton code et de sa structure implantée dans ton prog.
Elle fait quoi la fonction ReceptionImage.
Ton filtre doit s'arrêter, il y a un engine (thread) qui n'est pas stoppé regarde la doc ..., il y a certainement (obligatoirement) une api ou un callback qui permet de stopper l'acquisition/filtrage et de sortitr proprement.
...


Re : Probleme fermeture de Thread!!! le 16/06/2008 09:35:26

Dryko
Salut, je n'avais pas acces à Internet ce we, c'est pourquoi je n'ai pas pui répondre,

-Pour les destructeurs je suis d'accord mais ma classe CVirtualCam n'en a pas et si j'en créé un, il n'est pas apelé quand je detruit mon graphe DirectShow. :(
-La fonction ReceptionImage communique avec un autre PC et ne s'arrete jamais, c'est quand on detruit le graphe qu'on doit lui dire de s'arreter!
-Pour l'API qui permetterait de tout stopper proprement, là j'avoue que je bloque un peu(beaucoup).

Merci


[Page 1 Page 2]
Classé sous : application, probleme, fermeture, classe, thread

Participer à cet échange

Pub



Appels d'offres

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Boutique

Boutique de goodies CodeS-SourceS