3

I'm trying to write a typical stock trading program, which receives stock tickers/orders/trades from netmq, turn the streams into IObservable, and show them on a WPF frontend. I try to use async/await with NetMQ blocking ReceiveString (suppose I am expecting some string input) so that the ReceiveString loop wouldn't block the main (UI) thread. As I'm still new to C#, I take the answer of Dave Sexton in this post: (https://social.msdn.microsoft.com/Forums/en-US/b0cf96b0-d23e-4461-9d2b-ca989be678dc/where-is-iasyncenumerable-in-the-lastest-release?forum=rx) and trying to write some examples like this:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using NetMQ;
using NetMQ.Sockets;
using System.Reactive;
using System.Reactive.Linq;

namespace App1
{
    class MainClass
    {
        // publisher for testing, should be an external data publisher in real environment
        public static Thread StartPublisher(PublisherSocket s)
        {
            s.Bind("inproc://test");
            var thr = new Thread(() => {
                Console.WriteLine("Start publishing...");
                while (true) {
                    Thread.Sleep(500);
                    s.Send("hello");
                }
            });
            thr.Start();
            return thr;
        }

        public static IObservable<string> Receive(SubscriberSocket s)
        {
            s.Connect("inproc://test");
            s.Subscribe("");
            return Observable.Create<string>(
                async observer =>
                {
                    while (true)
                    {
                        var result = await s.ReceiveString();
                        observer.OnNext(result);
                    }
                });
        }

        public static void Main(string[] args)
        {
            var ctx = NetMQContext.Create();
            var sub = ctx.CreateSubscriberSocket();
            var pub = ctx.CreatePublisherSocket();
            StartPublisher(pub);

            Receive(sub).Subscribe(Console.WriteLine);
            Console.ReadLine();
        }
    }
}

It fails to compile with "cannot await string". While I understand it might be expecting a Task, I don't quite figure out how to get the whole thing up.

To wrap again: what I'm trying to achieve is simply get IObservable streams of ticker/orders/trades from netmq using simple blocking apis, but without really blocking the main thread.

Anything I can do with it? Thanks a lot.

Ralph Zhang
  • 5,015
  • 5
  • 30
  • 40

2 Answers2

6

I'm not familiar with NetMQ, but you really should structure you observable like this:

    public static IObservable<string> Receive(NetMQContext ctx)
    {
        return Observable
            .Create<string>(o =>
                Observable.Using<string, SubscriberSocket>(() =>
                {
                    var sub = ctx.CreateSubscriberSocket();
                    sub.Connect("inproc://test");
                    sub.Subscribe("");
                    return sub;
                }, sub =>
                Observable
                    .FromEventPattern<EventHandler<NetMQSocketEventArgs>, NetMQSocketEventArgs>(
                        h => sub.ReceiveReady += h,
                        h => sub.ReceiveReady -= h)
                    .Select(x => sub.ReceiveString()))
            .Subscribe(o));
    }

This will automatically create a SubscriberSocket for you and when the observable ends, .Dispose() will automatically be called on your socket.

Like I said, I'm not familiar with NetMQ, so the above code didn't receive any of the published messages so you will need to fiddle with it to get it to work, but this is a good starting point.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
2

ReceiveString is not awaitable, so just remove the await.

You can also read here how to make awaitable Socket: http://somdoron.com/2014/08/netmq-asp-net/

And take a look at the following article on using NetMQ with RX:

http://www.codeproject.com/Articles/853841/NetMQ-plus-RX-Streaming-Data-Demo-App

somdoron
  • 4,653
  • 2
  • 16
  • 24
  • Thanks a lot somdoron, I've read your article. Also Sasha's great demo was the direct reason that I use netmq/rx in my project. But I try to avoid the complexity of implementing an actor shown in the demo, so comes my previous question. Also If I remove the 'await' part, mono would warn about lack of 'await' in an async method, and visual studio 2013 would give error about 'Observer.Create()' call ambiguous. Not quite understand what it means. – Ralph Zhang Mar 15 '15 at 13:03
  • You need a dedicate thread to receive messages from a socket, this is way you have the actor thing. – somdoron Mar 18 '15 at 19:40