Я прочитал руководство ZeroMq и наткнулся на следующее:
НЕ ДОЛЖНО делиться сокетами ØMQ между потоками.Разъемы ØMQ не безопасны.Технически это возможно, но для этого требуются семафоры, блокировки или мьютексы.Это сделает ваше приложение медленным и хрупким.Единственное место, где удаленно делиться сокетами между потоками, - это языковые привязки, которые должны творить чудеса, такие как сборка мусора в сокетах.
и позже:
Помните: Не используйте и не закрывайте сокеты, кроме как в потоке, который их создал.
Я также понял, что ZeroMQ Context
является потокобезопасным.
Есликласс регистрирует событие другого класса, в .Net это событие может вызываться из потока, отличного от потока, в котором был создан прослушиватель.
Я думаю, что есть только две опции, которые можно отправитьчто-то через ZeroMQ-Sockets из обработчика событий:
- Синхронизировать поток-обработчик событий с потоком, в котором был создан ZeroMQ-
Socket
в - Создать новый ZeroMQ-
Socket
/ получить существующий ZeroMQ- Socket
для потока в обработчике событий, используя потокобезопасный ZeroMQ- Context
Похоже, что 0MQ-Guide поВо-первых, и я не думаю, что создание нового ZeroMq-Socket для каждого потока - это эффективный способ.
Мой вопрос :
Каков правильный шаблон(как это должно быть) публиковать сообщения через 0MQ из обработчика событий?
Кроме того, авторы руководства имели в виду ZeroMQ-Binding для .Net, когда писали:
Единственное место, где удаленно делиться сокетами между потоками, - это языковые привязки, которые должны творить чудеса, такие как сборка мусора в сокетах.?
Вот пример кода, чтобы подчеркнуть мою проблему / вопрос:
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?
}
}