Page 1 sur 2

tuto : mutex (suite)

Publié : dim. 20/juin/2004 14:56
par hardy
Me revoila!

Deux exemples simples :

Code : Tout sélectionner

nommutex.s="jesuisunmutex"
hmutex=CreateMutex_(0,0,@nommutex)

Global hmutex

Procedure proc1()
WaitForSingleObject_(hmutex,-1)
Repeat
Debug "a"
ForEver
EndProcedure

Procedure proc2()
WaitForSingleObject_(hmutex,-1)
Repeat
Debug "b"
ForEver
EndProcedure

CreateThread(@proc1(),0)
CreateThread(@proc2(),0)

Repeat
ForEver
et

Code : Tout sélectionner

Global hmutex

Procedure proc1()
Repeat
WaitForSingleObject_(hmutex,-1)
Debug "a"
ReleaseMutex_(hmutex)
ForEver
EndProcedure

Procedure proc2()
Repeat
WaitForSingleObject_(hmutex,-1)
Debug "b"
ReleaseMutex_(hmutex)
ForEver
EndProcedure

CreateThread(@proc1(),0)
CreateThread(@proc2(),0)

Repeat
ForEver
Le premier n'affiche que des "a" car le thread ne relâche pas le mutex.
Le second affiche des "a" et des "b" car le mutex est relâché.

Bon mais alors comment on fait pour créer une section annonce?

Réclame tutos "synchronisation" et "communication entre processus" :!:

Oubli : j'ai précedemment écrit une bétise. Pour attendre indéfiniment, temps=-1

Publié : dim. 20/juin/2004 15:20
par Chris
Pour créer une section "Annonce", il faut que l'admin accorde les droits dans l'administration du forum.

Chris :)

Publié : dim. 20/juin/2004 15:31
par hardy
Ah. Je ne demande pas ces droits. Mais si quelqu'un les ayant pouvait faire ça.
Chacun communiquerait des trucs à ajouter dans les rubriques.
Les deux points que j'ai évoqués, parmi d'autres, me semblent tout de même importants pour programmer des choses un peu compliquées.

Publié : dim. 20/juin/2004 15:39
par nico
Il manque l'instruction pour détruire un Mutex:

Code : Tout sélectionner

CloseHandle_(Hmutex)
:)

Publié : dim. 20/juin/2004 15:43
par Chris
Demande à Régis, il est admin, il doit avoir accès a la gestion des forums.

Chris :)

Publié : dim. 20/juin/2004 16:38
par hardy
Exact, oublié closehandle. :oops:
Promis, j'le ferais plus!

Publié : dim. 20/juin/2004 17:21
par nico
IL est à noter:

-que le nom pour la création d'un Mutex n'est nécessaire que si vous utilisez le Mutex pour une synchronisation inter-processus sinon ce paramètre peut-être mis à #Null.

-que la libération du Mutex "ReleaseMutex_(hmutex)" est réservée pour le Thread qui l'a obtenu. Donc un Thread qui a obtenu le Mutex peut lui seul le libérer pour qu'un autre Thread en attente puisse l'acquérir.

Publié : dim. 20/juin/2004 18:45
par hardy
Oui, c'est vrai que le nom n'est pas indispensable dans le cadre d'un seul processus.
Si par contre un autre processus veut utiliser le mutex, il récupère un handle avec createmutex et le nom (si le mutex existe déjà, createmutex ne fait qu'ouvrir le mutex préexistant)

Concernant la communication, j'utilise des sendmessage. Mais pas moyen de faire marcher correctement un pipe ou un mailslot. Quelqu'un y arrive? (j'avais déjà posé la question sans résultat...)

Publié : dim. 20/juin/2004 19:53
par Anonyme2
Il nous faut une rubrique Tutos car ils vont se perdre dans la quantité de messages ...

Publié : mar. 22/juin/2004 10:00
par hardy
Ben c'est ce que je demande. Ouh Ouh, y'a quelqu'un qui m'entend?

Publié : mar. 22/juin/2004 11:36
par nico
@Hardy

Je me suis documenté un peu, ce sont les pipes anonymes ou les pipes nommés qui t'intéressent ?

:)

Publié : mar. 22/juin/2004 18:04
par hardy
Les deux. Déjà, si tu arrives à en faire marcher un, je suis preneur !

Publié : mar. 22/juin/2004 19:06
par nico
Par rapport à ce que j'ai pu lire:

-Les pipes anonymes permettent l'échange de données entre process seulement sur une machine locale.

-Les pipes nommés et les maislots le permettent en réseau

Je me suis seulement intéressé aux pipes nommés qui sont les plus aboutis.

L'exemple ici n'a de valeur que pour l'expérimentation, j'ai omis volontairement les valeurs de retour de certaines fonctions.
Je n'ai testé ce code qu'en local, si tu veux l'essayer en réseau tu doit changer le chemin du pipe inscrit dans le string.
Normallement on doit doubler les "\" dans le chemin du pipe mais si je le fait, ça ne fonctionne plus! Bizarre.

Exécuter les deux applications,sur le server, faire menu creation d'un pipe nommé puis sur le client clicker sur le bouton.
Le server attend une connection, le client se connecte, envoie un message, le server le lit puis déconnecte le client.

J'espère que ça va t'aider, dis moi si ça marche en réseau! :)

Application Server:

Code : Tout sélectionner

#PIPE_ACCES_DUPLEX=3
#Gadget=0

Global Buffer_Ecriture.s,Buffer_Lecture.s,Envoie
Buffer_Ecriture=Space(100)
Buffer_Lecture=Space(100)


Procedure Thread_Client(pipe.l)
  fConnected = ConnectNamedPipe_(pipe, #Null)
  If fConnected
    AddGadgetItem(#Gadget, -1, "Un client est connecté")
  EndIf
  
  ReadFile_(pipe, @Buffer_Lecture, Len(Buffer_Lecture), @recu, 0)
  AddGadgetItem(#Gadget, -1, Buffer_Lecture)
  
  Buffer_Ecriture="Le serveur vous a déconnecté" 
  WriteFile_(pipe, Buffer_Ecriture, Len(Buffer_Ecriture), @envoye, 0)

  FlushFileBuffers_(pipe)
    
  If DisconnectNamedPipe_(pipe) 
    AddGadgetItem(#Gadget, -1, "Le server est en attente de connexion client") 
  EndIf
   Thread_Client(pipe.l) 
EndProcedure


If OpenWindow(0,0,0,600,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Server Pipe Nommé") And CreateGadgetList(WindowID(0)) 
  EditorGadget (#Gadget,10,10,580,160,#PB_Container_Raised)
  If CreateMenu(0, WindowID())
    MenuTitle("Action")
    MenuItem( 1, "Créer un pipe nommé")
    MenuItem( 2, "Quitter")
  EndIf
  
  Repeat
    EventID.l = WaitWindowEvent()
    Select EventID
      Case #PB_EventMenu 
        Select EventMenuID()
          Case 1
            Hpipe=CreateNamedPipe_("\\.\pipe\NomDePipe", #PIPE_ACCES_DUPLEX, #PIPE_TYPE_MESSAGE | #PIPE_READMODE_MESSAGE, 1, 100, 100, 3000, #Null) 
            If Hpipe
              AddGadgetItem(#Gadget, -1, "Le server est en attente de connexion client")
              Thread=CreateThread(@Thread_Client(),Hpipe)
            EndIf
             
          Case 2
            Quit = 1
        EndSelect
        
      Case #PB_Event_CloseWindow
        KillThread(Thread)
        CloseHandle_(Hpipe)
      Quit = 1
    EndSelect
    
  Until Quit = 1 
EndIf



Application Client:

Code : Tout sélectionner

#Gadget=0

Global Hpipe
Global Buffer_Ecriture.s,Buffer_Lecture.s
Buffer_Ecriture=Space(100)
Buffer_Lecture=Space(100)

Procedure AppelServer(Texte.s)
lpszPipename.s=GetGadgetText(3)
  
result=WaitNamedPipe_(lpszPipename, 3000)

Hpipe = CreateFile_( lpszPipename, #GENERIC_READ |#GENERIC_WRITE, 0, #Null, #OPEN_EXISTING,0, #Null)

If Hpipe
  Buffer_Ecriture.s=Texte
  WriteFile_(Hpipe, Buffer_Ecriture, @Len(Buffer_Ecriture), @envoye, 0)
  FlushFileBuffers_(Hpipe)
  
  ReadFile_(Hpipe, @Buffer_Lecture, Len(Buffer_Lecture), @recu, 0)
  AddGadgetItem(#Gadget, -1, Buffer_Lecture)  
EndIf
  
CloseHandle_(Hpipe)
EndProcedure

If OpenWindow(0,0,0,600,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Client Pipe Nommé") And CreateGadgetList(WindowID(0)) 
  EditorGadget (#Gadget,10,60,580,120,#PB_Container_Raised)
  StringGadget(1,10, 36,400,20,"Client: Voici un message")  
  ButtonGadget(2, 460, 36, 100, 20, "Envoyer")
  StringGadget(3,10, 10,400,20,"\\.\pipe\NomDePipe") 
  TextGadget(4, 420, 10,180,20,"Nom du serveur (Par défaut local ici)") 
    Repeat
      EventID.l = WaitWindowEvent()
      Select EventID
        Case #PB_EventGadget
          Select EventGadgetID()
            Case 2
              AppelServer(GetGadgetText(1))
          EndSelect 
          
        Case #PB_Event_CloseWindow
          Quit = 1
      EndSelect
 
    Until Quit = 1 
EndIf

Publié : mar. 22/juin/2004 23:13
par hardy
Je teste ça (pas en réseau, j'en n'ai pas !)
Mais d'après ce que tu dis ça doit être les "\" qui posaient problème (?! super la doc microsoft...)

Publié : mar. 22/juin/2004 23:16
par hardy
Ca marche !
Rien qu'une histoire de \...

Merci beaucoup.