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