0MQ: Comment utiliser ZeroMQ d'une manière threadsafe?
J'ai lu le ZeroMq guide et je suis tombé sur les éléments suivants:
Vous ne DEVEZ PAS partager ØMQ sockets entre
les threads. ØMQ sockets ne sont pas
des threads. Techniquement, c'est possible
pour ce faire, mais il exige des sémaphores,
des écluses ou des mutex. Cela permettra de rendre votre
application lente et fragile. La seule
lieu où il est à distance de sain d'esprit
partager sockets entre les threads sont en
liaisons de langage qu'il faut faire
la magie comme la collecte des ordures sur
sockets.
et plus tard:
Rappelez-vous: Ne pas utiliser ou de fermer les sockets, sauf dans le fil qui les a créés.
J'ai aussi compris que le ZeroMQ Context
est thread-safe.
Si une classe s'inscrit à un événement d'une autre classe, dans .Net, cet événement pourrait être appelée à partir d'un thread différent de celui de l'auditeur a été créé.
Je pense qu'il y a seulement deux options pour être en mesure d'expédier quelque chose via ZeroMQ-prises de courant à partir de l'intérieur d'un gestionnaire d'événements:
- Synchroniser le gestionnaire d'événements-invoquer-fil pour le fil de la ZeroMQ-
Socket
a été créé en - Créer un nouveau ZeroMQ-
Socket
/récupérer l'existant ZeroMQ-Socket
pour le thread dans le gestionnaire d'événements en utilisant les threads ZeroMQ-Context
Il semble que la 0MQ-Guide pour décourager à la première, et je ne pense pas que la création d'une nouvelle ZeroMq-Socket pour chaque thread est performant /le chemin à parcourir.
Ma Question:
Qu'est-ce que le modèle correct (la façon dont il est censé le faire) de publier des messages via 0MQ sein d'un gestionnaire d'événements?
De même, les auteurs du guide ont la ZeroMQ de Liaison pour .Net à l'esprit quand ils ont écrit:
Le seul
lieu où il est à distance de sain d'esprit
partager sockets entre les threads sont en
liaisons de langage qu'il faut faire
la magie comme la collecte des ordures sur
les sockets. ?
Voici quelques samplecode pour souligner mon problème/question:
public class ExampleClass
{
public event EventHandler<ByteEventArgs> SomethinIsCalledFromAnotherThread;
}
public class ByteEventArgs : EventArgs
{
public byte[] BytesToSend;
}
public class Dispatcher
{
ZMQ.Context ctx;
public Dispatcher(ZMQ.Context mqcontext, ExampleClass exampleClassInstance)
{
this.ctx = mqcontext;
exampleClassInstance.SomethinIsCalledFromAnotherThread += new EventHandler<ByteEventArgs>(exampleClass_SomethinIsCalledFromAnotherThread);
}
void exampleClass_SomethinIsCalledFromAnotherThread(object sender, ByteEventArgs e)
{
//this method might be called by a different thread. So I have to get a new socket etc?
using (var socket = ctx.Socket(ZMQ.SocketType.PUSH))
{
//init socket etc..... and finally:
socket.Send(e.BytesToSend);
}
//isn't that too much overhead?
}
}
source d'informationauteur tobsen
Vous devez vous connecter pour publier un commentaire.
.net framework v4 et vous pouvez utiliser la collecte simultanée de résoudre ce problème. À savoir les Producteurs et les Consommateurs motif. Plusieurs threads (gestionnaires) peut envoyer des données à un thread-safe file d'attente et juste un seul thread utilise des données de la file d'attente et l'envoie à l'aide de la douille.
Voici l'idée:
Vous pouvez créer beaucoup de 0MQ sockets, certainement autant que vous avez des threads. Si vous créez un socket dans un thread, et de l'utiliser dans un autre, vous devez exécuter une mémoire pleine de barrière entre les deux opérations. Tout autre résultat sera bizarre aléatoire des échecs dans libzmq, comme les objets socket ne sont pas thread-safe.
Il y a quelques schémas classiques, mais je ne sais pas comment ces carte spécialement pour .NET:
N'oubliez pas de jeter un coup d'oeil à la inproc de transport. Il pourrait être utile d'utiliser inproc://sockets pour interthread de la communication et avoir un thread qui s'ouvre sockets de parler à d'autres processus/serveurs.
Vous avez encore besoin d'au moins une prise par thread, mais la inproc ceux n'impliquent pas l'IP de la couche réseau.