0MQ: Как использовать ZeroMQ для обеспечения безопасности потоков?

Я прочитал руководство по ZeroMq и наткнулся на следующее:

Вы НЕ ДОЛЖНЫ совместно использовать сокеты ØMQ между потоки. Розетки ØMQ не потокобезопасный. Технически это возможно для этого, но это требует семафоров, замки или мьютексы. Это сделает ваш приложение медленное и хрупкое. Единственный место, где это отдаленно разумно общие сокеты между потоками находятся в языковые привязки, которые нужно сделать магия как сборка мусора на сокеты.

и позже:

Помните: Не используйте и не закрывайте сокеты, кроме потока, который их создал.

Я также понял, что ZeroMQ Контекст является потокобезопасным.

Если класс регистрируется для события другого класса в .Net, это событие может быть вызвано из потока, отличного от потока, в котором был создан слушатель.

Я думаю, что есть только два варианта, чтобы иметь возможность для отправки чего-либо через ZeroMQ-Sockets из обработчика событий:

  • Синхронизируйте поток, вызывающий обработчик событий, с потоком, в котором был создан ZeroMQ- Socket в
  • . Создайте новый ZeroMQ- Socket / получите существующий ZeroMQ- Socket для потока в обработчике событий с использованием потокобезопасного ZeroMQ- Context

Кажется, что руководство 0MQ не одобряет первый, и я не думаю, что создание нового ZeroMq-Socket для каждого поток является исполнителем / путь к успеху.

Мой вопрос :
Каков правильный шаблон (каким он должен быть) для публикации сообщений через 0MQ из обработчика событий?

Кроме того, имели в виду авторы руководства ZeroMQ-Binding для .Net, когда писали:

Единственный место, где это отдаленно разумно общие сокеты между потоками находятся в языковые привязки, которые нужно сделать магия как сборка мусора на Розетки. ?

Вот пример кода, чтобы подчеркнуть мою проблему / вопрос:

public class ExampleClass
{
    public event EventHandler 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(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?
    }
}

17
задан tobsen 28 May 2013 в 18:44
поделиться