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

MFC Discussion :

Thread et Timer en parallèle et probleme de mis a jour control bar-progress


Sujet :

MFC

  1. #1
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut Thread et Timer en parallèle et probleme de mis a jour control bar-progress
    Bonjour,

    J'ai une application qui utilise du multithreading mais il me semble que la fonction OnTimer (et plus exactement un focntion a l'interieur) bloque, fige mon application car le barprogresse qui se met a jour tous les 100m secondes ne change cette fois que tous les 4 à 5 secondes.

    la ligne qui pose probleme est celle ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connected=cp.Init("192.0.2.2");
    Si je mets en commentaires mon barprogresse fonctionne correctement.

    Au départ mon code de mis a jour du barprogress se trouvait dans la fonction OnTimer au depart.

    Et j'ai pensé à une thread justement pour éviter que le barprogress ne ralentisse mais ça ne va pas, est ce que j'utilise mal
    le threading ?

    Est-ce que le probleme est lié à 'utilisation d'un Timer MFC avec un thread en parallèle ou bien est ce que j'ai une erreur dans mon code (voir ci-dessous) ?

    Merci



    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
     
     
     
     
    BOOL CDlg_2::OnInitDialog() 
    {
        ....
     
    	THREADINFOSTRUCT *tis=new THREADINFOSTRUCT;
     
    	tis->hWnd=m_hWnd;
    	tis->someData="This is in a thread.";
     
     
    	                                                       //call to thread for bar progress
    	CWinThread *pThread = AfxBeginThread(MyThreadFunc,tis,   
    	THREAD_PRIORITY_HIGHEST,0,0);  // THREAD_PRIORITY_NORMAL THREAD_PRIORITY_HIGHEST
     
    	connected =false;
    	SetTimer(3,1000,0);  //call to OnTImer
     
    	return TRUE;  // return TRUE unless you set the focus to a control
     
    }
     
     
     
    UINT MyThreadFunc(LPVOID lParam)
    {
    	THREADINFOSTRUCT* tis=(THREADINFOSTRUCT*)lParam;
     
    	if(wrong_exit==true)
    	good_finish ==true;
     
    	while(good_finish==false)
    	{
    		int i=3;
    		SendMessage(tis->hWnd,WM_USER_THREAD_UPDATE_PROGRESS,i,100);  //SendMessage  PostMessage
    		DoEvents();
    		Sleep(100);
    	}
     
    	if(good_finish ==true)
    	PostMessage(tis->hWnd,WM_USER_THREAD_FINISHED,0,0);
     
    	delete tis;
    	return 0;
    }
     
    LRESULT CDlg_2::OnThreadFinished(WPARAM wParam,LPARAM lParam)
    {
    //AfxMessageBox("Thread has exited");
    return 0;
    }
    LRESULT CDlg_2::OnThreadUpdateProgress(WPARAM wParam,LPARAM lParam)
    {
     
    	RedrawWindow();  //for trying to refresh window dialog 
     
    		if(progressindex ==100)
    			progressindex=0;
    		else
    			progressindex+=10;
     
    		m_progress2.SetPos(progressindex);
     
    	return 0;
    }
     
    int DoEvents()
    {
         MSG msg;
         int nCount = 0;
     
         while ( ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE) )
         {
              nCount++;
              ::TranslateMessage(&msg);
              ::DispatchMessage(&msg);
         }
     
         return nCount;
    }
     
     
     
    void CDlg_2::OnTimer(UINT nIDEvent) 
    {
    	// TODO: Add your message handler code here and/or call default
    	UpdateData(TRUE);
    	..
     
        if (nIDEvent ==3)  //timer for progress bar
    	{	
     
    		//KillTimer(3);
    		GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(false); 
     
     
    //commented because trying to done by MyThreadFunc 
    /*
    				if (posprogress2==100)
    				{
    					//091002
    					posprogress2=10;  
    				}
    				else
    				{
    					//091002
    					posprogress2+=10;
    				}
    				//091002
    				m_progress2.SetPos(posprogress2);
    */
    				if ((connected==1) && (already_pass==false))
    				{
    					//091002
    					//GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(true); 
     
    					m_progress2.SetPos(0);
    					first_msg =false;
    					m_static_msg1.SetWindowText(NULL);
    					already_pass =true;
    				}
    				else if (forcetest==0)
    				{
     
    				OnButtonBegin();  //this function contain a system function that slow the application
    				}
     
    	}
    		UpdateData(FALSE);
    	CDialog::OnTimer(nIDEvent);
    }
     
     
    void CDlg_2::OnButtonBegin() 
    {
    	// TODO: Add your control notification handler code here
     
    	CWaitCursor();
     
    	SHELLEXECUTEINFO sei5;   //091001
    	DWORD dw;  //091001
     
    	KillTimer(3);
     
    	GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(false);
     
    	if (process_0)
    	{
     
    					process_0 =false;
    					process_1= true;
     
    	}
    	else if (process_1)
    	{
    		//MessageBox("in process1");
    		//try //
    		{
    			connected=cp.Init("192.0.2.2"); //This calling blocks the application. When removing the 
    			                                //barporgress run well otherwise it the barprogress is very slow.
    		}
     
    	//	catch(...)
    		{
    				//MessageBox("Problem of Init Fxcam", "Exception Message");
    				//KillTimer(3);
    				//m_progress2.SetPos(0);
    				//GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(true); 
    		}
    		if (connected==1)
    		{
     
    		...
     
    	}	
    	else if (process_2)
    	{
    	..
    	}
     
    	....
     
    	if(good_finish==true)
    	KillTimer(3);
    	else
    	SetTimer(3,200,0);
     
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 166
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 166
    Points : 12 284
    Points
    12 284
    Par défaut
    Je n'ai pas lu le code fournis, mais la règle générale (qui a des fondements très précis mais que je n'ai pas le temps de décrire ici) est de faire toutes les actions lié à l'IHM dans le thread d'IHM, couramment le thread principale (celui par défaut) et de faire les actions qui coûts du temps dans des threads auxiliaires (dits Working Threads).

    Donc, dans votre cas de figure, vous faîtes le "connected=cp.Init("192.0.2.2");" dans un thread auxiliaire et vous conservez le code de mise à jour de la progresse par dans le thread principal (dans la méthode OnTimer).

    Et j'ai pensé à une thread justement pour éviter que le barprogress ne ralentisse mais ça ne va pas, est ce que j'utilise mal
    le threading ?
    Oui, vous utilisez mal le threading, mais on a tous commencé par se planter avec les threads.

    Est-ce que le problème est lié à 'utilisation d'un Timer MFC avec un thread en parallèle ou bien est ce que j'ai une erreur dans mon code (voir ci-dessous) ?
    Le problème n'est pas lié au MFC donc

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    J'ai pas tout lu mais je soupçonne que THREAD_PRIORITY_HIGHEST empêche ton thread IHM de prendre la main.
    Je pense que DoEvents appelé dans ton thread ne sert à rien.

  4. #4
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut
    Effectivement j'ai enlevé le DoEvents inutile.
    Et remplacé ceci THREAD_PRIORITY_HIGHEST par THREAD_PRIORITY_NORMAL mais ça n'a pas resoud le problème.

    Et donc cette fois j'ai mis la fonction OnButtonBegin dans la thread et laisser le Ontimer s'occuper du bar progress.
    Mais toujours le même problème même si je dedie une thread pour la fonction OnButtonBegin() ça bloque quand même
    l'application. C'est à ce dire si je n'ai pas simplement une fonction toute simple à la place d'une fonction thread ??

    Le code ci-dessous me semble correct non ?

    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
     
     
    BOOL CDlg_2::OnInitDialog() 
    {
    	CDialog::OnInitDialog();
     
    	....
     
     
    	//MessageBox("start the thread");
    	THREADINFOSTRUCT *tis=new THREADINFOSTRUCT;
     
    	tis->hWnd=m_hWnd;
    	tis->someData="This is in a thread.";
     
     
    	CWinThread *pThread = AfxBeginThread(MyThreadFunc,tis,
    	THREAD_PRIORITY_NORMAL,0,0);  // THREAD_PRIORITY_NORMAL THREAD_PRIORITY_HIGHEST
     
    	connected =false;
    	SetTimer(3,1000,0);
        GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(false);  
     
    	return TRUE;  // return TRUE unless you set the focus to a control
    	              // EXCEPTION: OCX Property Pages should return FALSE
    }
     
     
    void CDlg_2::OnTimer(UINT nIDEvent) 
    {
        if (nIDEvent ==3) //timer for progress bar
    	{	
     
    		RedrawWindow();
     
    		if (posprogress2==100)
    		{
    			posprogress2=10;  			
    		}
    		else
    		{
    			posprogress2+=10;
    		}
     
    		m_progress2.SetPos(posprogress2);
     
    		if ((connected==1) && (already_pass==false))
    		{
    			m_progress2.SetPos(0);
    			first_msg =false;
    			m_static_msg1.SetWindowText(NULL);
    			already_pass =true;
     
    			KillTimer(3);//091008
    		}
    		else if (forcetest==0)
    		{
     
    	//	OnButtonBegin();  //mis dans la thread
    		SetTimer(3,300,0);
    		}
     
    	}
    	UpdateData(FALSE);
    	CDialog::OnTimer(nIDEvent);
    }
     
     
     
    // thread 
    UINT MyThreadFunc(LPVOID lParam)
    {
    	THREADINFOSTRUCT* tis=(THREADINFOSTRUCT*)lParam;
     
     
    	if(wrong_exit==true)
    	good_finish ==true;
     
    	while(good_finish==false)
    	{
    		int i=3;
    		SendMessage(tis->hWnd,WM_USER_THREAD_UPDATE_PROGRESS,i,100);  //SendMessage  PostMessage
    		//DoEvents();
    		Sleep(1500); //
     
    	}
     
    	if(good_finish ==true)
    	PostMessage(tis->hWnd,WM_USER_THREAD_FINISHED,0,0);
     
    	delete tis;
    	return 0;
    }
     
    LRESULT CDlg_2::OnThreadFinished(WPARAM wParam,LPARAM lParam)
    {
    //AfxMessageBox("Thread has exited");
    return 0;
    }
     
    LRESULT CDlg_2::OnThreadUpdateProgress(WPARAM wParam,LPARAM lParam)
    {
    	//m_progress2.SetPos(100*(int)wParam/(int)lParam);
    	RedrawWindow();
     
            /*
    		if(progressindex ==100)
    			progressindex=0;
    		else
    			progressindex+=10;
     
     
    		m_progress2.SetPos(progressindex);
    		*/
    	OnButtonBegin() ;
     
    	return 0;
    }
     
    void CDlg_2::OnButtonBegin() 
    {
    	// TODO: Add your control notification handler code here
    	CWaitCursor();
     
    	SHELLEXECUTEINFO sei5; 
    	DWORD dw;  
     
    	GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(false);
     
    	if (process_0)
    	{
    		process_0 =false;
    		process_1= true;
    	}
    	else if (process_1)
    	{
         //try
    		{
    		connected=cp.Init("192.0.2.2"); //Fonction qui pose probleme
    		}
     
    	//	catch(...)
    		{
    				//MessageBox("Problem of Init", "Exception Message");
     
    		}
    		if (connected==1)
    		{
    						process_1 =false;
    						process_2= true;
            }
    	}
    	...
     
    }


    Comment resoudre ce bloquage de l'application, une thread n'est ce pas suffisant?

    Merci

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Peux tu mettre un point d'arrêt pour voir que fait ton thread I.H.M. ? Ne serait-il pas tous simplement bloqué dans la fonction OnButtonBegin qui prend du temps ? L'appel à connect ne serait-il pas bloquant ?

  6. #6
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut
    Oui,
    effectivement l'appel à la fonction connect est bloquant car si je la commente mon appli fonctionne tres bien sans aucun bloquage.

    Par contre si je laisse active la fonction connect dans OnButtonBegin() alors mon appli fonctionne bien seulement durant le sleep de ma thread (isi 1500 ms), donc ça veut bien dire que ma thread fonctionne normalement mais que c'est bien au passage à la fonction connect qui le problème a lieu.

    C'est inquiétant de perdre le control de l'application.

    Quelle pourrait être la solution ?

    Merci

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Déporter connect dans un thread de travail pour ne pas figer l'I.H.M. est la solution à priori pertinente ... sauf que je ne connais pas connect. Donc plusieurs questions surgissent :
    -> existe-t-il une version non bloquante de connect permettant juste d'être notifié de son résultat ou de faire du polling. Je pense à ça car connect me fait penser à une connection TCP. Auquel cas il y a mieux à faire que de passer par un thread.
    -> connect supporte-t-elle la concurrence, i.e. peut-on l'appeler de n'importe quel thread ?

  8. #8
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut
    >> Déporter connect dans un thread de travail pour ne pas figer l'I.H.M. est >> la solution à priori pertinente


    N'utilise je pas un thread de travail ?

    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
     
    LRESULT CDlg_2::OnThreadFinished(WPARAM wParam,LPARAM lParam)
    {
    //AfxMessageBox("Thread has exited");
    return 0;
    }
     
    LRESULT CDlg_2::OnThreadUpdateProgress(WPARAM wParam,LPARAM lParam)
    {
    	RedrawWindow();
    	OnButtonCamera2() ;
    	return 0;
    }
     
     
     
    UINT MyThreadFunc(LPVOID lParam)
    {
    	THREADINFOSTRUCT* tis=(THREADINFOSTRUCT*)lParam;
     
    	if(wrong_exit==true)
    	good_finish ==true;
     
    	while(good_finish==false)
    	{
    		int i=3;
    		SendMessage(tis->hWnd,WM_USER_THREAD_UPDATE_PROGRESS,i,100);  //SendMessage  PostMessage
    		//DoEvents();
    		Sleep(1500);
     
    	}
    	if(good_finish ==true)
    	PostMessage(tis->hWnd,WM_USER_THREAD_FINISHED,0,0);
     
    	delete tis;
    	return 0;
    }

    Et mon appel à la thread a lieu dans OnInitDialog() :
    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
     
     
    	...
     
    	THREADINFOSTRUCT *tis=new THREADINFOSTRUCT;
    	tis->hWnd=m_hWnd;
    	tis->someData="This is in a thread.";
     
                //MessageBox("start the thread");
    	CWinThread *pThread = AfxBeginThread(MyThreadFunc,tis,
    		THREAD_PRIORITY_NORMAL,0,0);  //
     
                	connected =false;
    	SetTimer(3,100,0);
              GetDlgItem(IDC_BUTTON_CAMERA2)->EnableWindow(false);
    A ma connaissance un thread de travail se declare comme ceci:
    "
    UINT MyThreadFunc(LPVOID lParam)
    {
    "

    Je sais pas peut être qu'il s'agit d'un thread UI parceque'il y a des messages ?


    Merci

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    On résume : connect est la fonction bloquante.
    Ton scénario devrait ressembler à :
    Thread Dialog :
    1/ création du thread de travail
    2/ Mise en place du timer
    3/ Sur évènement timer : avancement de la progress bar.

    Thread de travail :
    1/ Exécution du connect
    2/ Notification au thread dialog via un PostMessage(HWND,...) de la fin du connect.

    Ensuite : il faut faire attention à ce que les objets manipulés par connect :
    1/ supportent d'être appelés dans un thread différent de celui qui les a créé
    2/ sont éventuellement protégés contre des accès concurrents s'ils sont partagés entre le thread de travail et le thread principal (IHM/Dialog).

  10. #10
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut
    Salut,

    Mon thread Dialog est bon me semble t il ?

    Par contre pour le thread de Travail j'execute la fonction
    OnButtonBegin qui elle contient la focntion connect
    mais les messages pourquoi et comment dois je les envoyé au dialog ?

    En parlant de thread Dialog, je suppose qu'il s'agit de l'application même ?
    Dois je faire thread IHM en plus du thread de travail ?



    Merci

Discussions similaires

  1. [EJB3 Entity] Probleme de mis a jour ManyToMany
    Par doblern dans le forum Java EE
    Réponses: 3
    Dernier message: 12/04/2008, 19h26
  2. Probleme de mis a jour ManyToMany
    Par kore62 dans le forum JPA
    Réponses: 3
    Dernier message: 08/01/2008, 02h11
  3. probleme apres mis a jour
    Par Blo0d4x3 dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 18/08/2006, 21h36
  4. [swing] Probleme de thread avec Timer
    Par issou dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 13/05/2006, 22h52
  5. Probleme servlet mis a jours
    Par yuriashford dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 24/04/2006, 15h03

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