OVH Cloud OVH Cloud

Programmer un sémaphore en VB.net ?

7 réponses
Avatar
Bull
Bonjour à tous,

J'aimerais programmer un sémaphore en VB.net. Je ne connaissais pas le terme
avant mais en fait en cherchant sur le net, j'ai trouvé que c'était
exactement ce qu'il me fallait :

http://mdalbin.developpez.com/tutoriels/general/semaphores/#L1.1

Sur cette page, il donne le code en Java. Il est relativement simple mais je
n'arrive pas à transcrire en VB.net 2-3 petits bouts.

En java, il donne ceci :
public class Semaphore
{
private int valeur;
private int limite;

public Semaphore(int valeur, int limite)
{
this.valeur=valeur;
this.limite=limite;
}

public int getValeur()
{
return valeur;
}

synchronized public void P()
{
while (valeur<1)
{
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Erreur de Sémaphore");
}
}
valeur=valeur-1;
}

synchronized public void V()
{
valeur=valeur+1;
notify();
}
}
Les points dont je n'arrive pas à trouver l'équivalent en VB.net sont :

- la propriété "synchronized" des deux dernières procédures
- le "wait();"
- le "notify();" (mais je ne vois pas à quoi il sert)

Quelqu'un pourrait-il m'aider à transcrire cette classe bien utile en VB.net
?

Merci d'avance,
Cordialement,
Bull

7 réponses

Avatar
Bull
Petit complément d'information en espérant que cela pourra aider à
comprendre mon problème. J'espère que quelqu'un pourra ainsi m'aider, car je
bloque depuis une semaine sans avancer d'un pas ? :-(

Je dois lancé en parallèle disons 100 fois une procédure que j'appelle
"working()". J'utilise donc un ThreadPool pour les lancer. Or, je veux que
le système ne traite en même que 5 et que les 95 autres attendent qu'une
place se libère. Pour cela, dans working() j'appelle :

Dim slot As Integer = semaphore.Wait()

(voir ci-dessous ma classe semaphore)
slot correspond au numéro parmi les 5 emplacements de travail qui a été
attribué pour la tâche en cours

Une fois working() terminée, j'appelle pour libérer la place :
semaphore.Release(slot)


La classe semaphore est la suivante :
Imports System

Imports System.Threading

Public Class Semaphore

'array of mutex on which the threads wait

Private m_mutex() As Mutex

'semaphore count

Private m_threadLimit As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

m_threadLimit = threadLimit

ReDim Preserve m_mutex(m_threadLimit - 1)

Dim i As Integer

For i = 0 To m_threadLimit - 1

m_mutex(i) = New Mutex

Next

End Sub

'if there is a timeout then WaitHandle.WaitTimeout is returned

'calling thread should check for this

Public Function Wait() As Integer

Dim slot As Integer = WaitHandle.WaitTimeout

While (slot = WaitHandle.WaitTimeout)

slot = WaitHandle.WaitAny(m_mutex)

End While

Return slot

End Function

'release the mutex locked by the thread

Public Sub Release(ByVal slot As Integer)

m_mutex(slot).ReleaseMutex()

End Sub

End Class


Pour les 5 premiers ThreadPool, cela semble fonctionner. Mais pour les
autres, ça bloque et j'ai l'impression que le timeout des waithandles est
atteint et du coup, la majeure partie de mes 100 tâches à traiter ne le sont
pas :-(
(je ne sais pas si je m'exprime bien).

Quelqu'un pourrait-il m'aider, car je bloque depuis une semaine sans avancer
d'un pas ? :-(

Merci d'avance,

--
Cordialement,
Bull


"Bull" a écrit dans le message de news:

Bonjour à tous,

J'aimerais programmer un sémaphore en VB.net. Je ne connaissais pas le
terme avant mais en fait en cherchant sur le net, j'ai trouvé que c'était
exactement ce qu'il me fallait :

http://mdalbin.developpez.com/tutoriels/general/semaphores/#L1.1

Sur cette page, il donne le code en Java. Il est relativement simple mais
je n'arrive pas à transcrire en VB.net 2-3 petits bouts.

En java, il donne ceci :
public class Semaphore
{
private int valeur;
private int limite;

public Semaphore(int valeur, int limite)
{
this.valeur=valeur;
this.limite=limite;
}

public int getValeur()
{
return valeur;
}

synchronized public void P()
{
while (valeur<1)
{
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Erreur de Sémaphore");
}
}
valeur=valeur-1;
}

synchronized public void V()
{
valeur=valeur+1;
notify();
}
}
Les points dont je n'arrive pas à trouver l'équivalent en VB.net sont :

- la propriété "synchronized" des deux dernières procédures
- le "wait();"
- le "notify();" (mais je ne vois pas à quoi il sert)

Quelqu'un pourrait-il m'aider à transcrire cette classe bien utile en
VB.net ?

Merci d'avance,
Cordialement,
Bull




Avatar
Zazar
Bonjour,


En java, il donne ceci :



<snip code>
Les points dont je n'arrive pas à trouver l'équivalent en VB.net so nt :

- la propriété "synchronized" des deux dernières procédures



Le mot-clef synchronized empêche que 2 threads appellent simultanémen t
l'une ou l'autre des méthodes. En VB.NET, on peut avoir ce comportement
avec la classe Monitor. Au début de chacune des méthodes, il suffit d e
mettre un :
Monitor.Enter(me)
et à la fin
Monitor.Exit(me).

Aprés il faut s'assurer qu'à chaque enter corresponde bien un leave : un
try/Finally est fortement conseillé.

- le "wait();"
- le "notify();" (mais je ne vois pas à quoi il sert)



Le wait sur un objet bloque le thread courant jusqu'à ce qu'un autre
thread fasse un notify sur le même objet
Les équivalents .NET sont Monitor.Wait(object) et Monitor.Pulse(object) .

Bon courage,

--
Zazar
Avatar
Bull
Bonjour Zazar,

Merci beaucoup pour ta réponse mais hélas, je bloque toujours. Au lieu du
Monitor, j'avais utilisé l'objet Mutex mais le résultat est le même hélas.

Voici comment j'ai traduit la classe Semaphore en VB.net :
Imports System

Public Class Semaphore

Private freeSlotsMonitor As Monitor

Private freeSlots As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

freeSlots = threadLimit

End Sub

Public Sub Acquire()

Try

freeSlotsMonitor.Enter(Me)

While freeSlots <= 0

freeSlotsMonitor.Wait(Me)

End While

freeSlots -= 1

Catch ex As Exception

MsgBox(ex.Message)

Finally

freeSlotsMonitor.Pulse(Me)

freeSlotsMonitor.Exit(Me)

End Try

End Function

'release the mutex locked by the thread

Public Sub Release(ByVal slot As Integer)

Try

freeSlotsMonitor.Enter(Me)

freeSlots += 1

Finally

freeSlotsMonitor.Exit(Me)

End Try

End Sub

End Class


Maintenant, le problème vient peut être de comment je l'emploie. Voici
quelques explications :
J'ai une classe dont une méthode "launchThread" est lancée. Cette dernière
en fait par le biais d'une boucle FOR lance dans un ThreadPool X fois la
méthode "works". Dans cette méthode, je fais tout d'abord un :

semaphore.Acquire()

Puis, je mets mes lignes de code. Et enfin, je fais un :
semaphore.Release()

Merci d'avance,

--
Cordialement,
Bull


"Zazar" a écrit dans le message de
news:
Bonjour,


En java, il donne ceci :



<snip code>
Les points dont je n'arrive pas à trouver l'équivalent en VB.net sont :

- la propriété "synchronized" des deux dernières procédures



Le mot-clef synchronized empêche que 2 threads appellent simultanément
l'une ou l'autre des méthodes. En VB.NET, on peut avoir ce comportement
avec la classe Monitor. Au début de chacune des méthodes, il suffit de
mettre un :
Monitor.Enter(me)
et à la fin
Monitor.Exit(me).

Aprés il faut s'assurer qu'à chaque enter corresponde bien un leave : un
try/Finally est fortement conseillé.

- le "wait();"
- le "notify();" (mais je ne vois pas à quoi il sert)



Le wait sur un objet bloque le thread courant jusqu'à ce qu'un autre
thread fasse un notify sur le même objet
Les équivalents .NET sont Monitor.Wait(object) et Monitor.Pulse(object).

Bon courage,

--
Zazar
Avatar
Bull
Petit complément d'info, je viens de me rendre compte que mes ThreadPool en
attente crée une exception qui est la suivante :

"Le nombre de threads libres dans l'objet ThreadPool n'est pas suffisant
pour terminer l'opération."

Que puis-je faire pour y remédier ??

Merci d'avance pour votre aide
--
Cordialement,
Bull


"Bull" a écrit dans le message de news:

Bonjour Zazar,

Merci beaucoup pour ta réponse mais hélas, je bloque toujours. Au lieu du
Monitor, j'avais utilisé l'objet Mutex mais le résultat est le même hélas.

Voici comment j'ai traduit la classe Semaphore en VB.net :
Imports System

Public Class Semaphore

Private freeSlotsMonitor As Monitor

Private freeSlots As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

freeSlots = threadLimit

End Sub

Public Sub Acquire()

Try

freeSlotsMonitor.Enter(Me)

While freeSlots <= 0

freeSlotsMonitor.Wait(Me)

End While

freeSlots -= 1

Catch ex As Exception

MsgBox(ex.Message)

Finally

freeSlotsMonitor.Pulse(Me)

freeSlotsMonitor.Exit(Me)

End Try

End Function

'release the mutex locked by the thread

Public Sub Release(ByVal slot As Integer)

Try

freeSlotsMonitor.Enter(Me)

freeSlots += 1

Finally

freeSlotsMonitor.Exit(Me)

End Try

End Sub

End Class


Maintenant, le problème vient peut être de comment je l'emploie. Voici
quelques explications :
J'ai une classe dont une méthode "launchThread" est lancée. Cette dernière
en fait par le biais d'une boucle FOR lance dans un ThreadPool X fois la
méthode "works". Dans cette méthode, je fais tout d'abord un :

semaphore.Acquire()

Puis, je mets mes lignes de code. Et enfin, je fais un :
semaphore.Release()

Merci d'avance,

--
Cordialement,
Bull


"Zazar" a écrit dans le message
de news:
Bonjour,


En java, il donne ceci :



<snip code>
Les points dont je n'arrive pas à trouver l'équivalent en VB.net sont :

- la propriété "synchronized" des deux dernières procédures



Le mot-clef synchronized empêche que 2 threads appellent simultanément
l'une ou l'autre des méthodes. En VB.NET, on peut avoir ce comportement
avec la classe Monitor. Au début de chacune des méthodes, il suffit de
mettre un :
Monitor.Enter(me)
et à la fin
Monitor.Exit(me).

Aprés il faut s'assurer qu'à chaque enter corresponde bien un leave : un
try/Finally est fortement conseillé.

- le "wait();"
- le "notify();" (mais je ne vois pas à quoi il sert)



Le wait sur un objet bloque le thread courant jusqu'à ce qu'un autre
thread fasse un notify sur le même objet
Les équivalents .NET sont Monitor.Wait(object) et Monitor.Pulse(object).

Bon courage,

--
Zazar



Avatar
Zazar
Bonsoir,

<...>

Private freeSlotsMonitor As Monitor



Vous n'avez pas besoin d'une variable de type Monitor, vous n'utilisez
que des méthodes shared ici.

Private freeSlots As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

freeSlots = threadLimit

End Sub

Public Sub Acquire()

Try

freeSlotsMonitor.Enter(Me)

While freeSlots <= 0

freeSlotsMonitor.Wait(Me)

End While

freeSlots -= 1

Catch ex As Exception

MsgBox(ex.Message)

Finally

freeSlotsMonitor.Pulse(Me)



L'appel à Pulse() est mal placé, il doit avoir lieu dans la méthode
Release() (comme la méthode notify() en java).


--
Zazar
Avatar
Bull
Bonsoir,

Merci pour ta réponse. Mais ça ne fonctionne toujours pas correctement. J'ai
toujours pour la grande majorité de mes threadPool l'exception suivante qui
est levée : Message "Le nombre de threads libres dans l'objet ThreadPool
n'est pas suffisant pour terminer l'opération. " String

Une idée sur comment l'éviter ?

Merci d'avance,

--
Cordialement,
Bull


"Zazar" a écrit dans le message de
news:
Bonsoir,

<...>

Private freeSlotsMonitor As Monitor



Vous n'avez pas besoin d'une variable de type Monitor, vous n'utilisez
que des méthodes shared ici.

Private freeSlots As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

freeSlots = threadLimit

End Sub

Public Sub Acquire()

Try

freeSlotsMonitor.Enter(Me)

While freeSlots <= 0

freeSlotsMonitor.Wait(Me)

End While

freeSlots -= 1

Catch ex As Exception

MsgBox(ex.Message)

Finally

freeSlotsMonitor.Pulse(Me)



L'appel à Pulse() est mal placé, il doit avoir lieu dans la méthode
Release() (comme la méthode notify() en java).


--
Zazar
Avatar
Bull
J'ai réussi à résoudre mon problème. Apparement, (enfin je pense), le
problème ne venait pas de ma classe Semaphore mais de la classe qui
l'utilisait :)

Encore merci pour ton aide

--
Cordialement,
Bull


"Bull" a écrit dans le message de news:

Bonsoir,

Merci pour ta réponse. Mais ça ne fonctionne toujours pas correctement.
J'ai toujours pour la grande majorité de mes threadPool l'exception
suivante qui est levée : Message "Le nombre de threads libres dans
l'objet ThreadPool n'est pas suffisant pour terminer l'opération. " String

Une idée sur comment l'éviter ?

Merci d'avance,

--
Cordialement,
Bull


"Zazar" a écrit dans le message
de news:
Bonsoir,

<...>

Private freeSlotsMonitor As Monitor



Vous n'avez pas besoin d'une variable de type Monitor, vous n'utilisez
que des méthodes shared ici.

Private freeSlots As Integer

'constructor which initializes and sets the mutexes

Public Sub New(ByVal threadLimit As Integer)

freeSlots = threadLimit

End Sub

Public Sub Acquire()

Try

freeSlotsMonitor.Enter(Me)

While freeSlots <= 0

freeSlotsMonitor.Wait(Me)

End While

freeSlots -= 1

Catch ex As Exception

MsgBox(ex.Message)

Finally

freeSlotsMonitor.Pulse(Me)



L'appel à Pulse() est mal placé, il doit avoir lieu dans la méthode
Release() (comme la méthode notify() en java).


--
Zazar