2

I have my c# form running two threads one thread listens for data to come in and the other is processing the data so i can use it. for some reason once the process thread starts the listen thread isn't executed any more.

Thread th1 = new Thread(new ThreadStart(zeroMQConn.Listen));
th1.Start();
Thread th2 = new Thread(() => ProcessData(zeroMQConn));
th2.Start();

when i debug this it starts the th1 goes into it and then th2 starts and it never goes back to th1 and my data comes back null.

public void Listen()
    {
        while (true)
        {
            try
            {
                byte[] zmqBuffer = new byte[102400];
                int messageLength;
                lockForZMQ.EnterWriteLock();
                messageLength = socket.Receive(zmqBuffer);
                lockForZMQ.ExitWriteLock();
                byte[] message = new byte[messageLength];
                Buffer.BlockCopy(zmqBuffer, 0, message, 0, messageLength);
                PriceBookData priceBook = PriceBookData.CreateBuilder().MergeFrom(message).Build();
                double Type = priceBook.GetPb(0).QuoteType;
                if (Type == 0.0)
                {
                    lockForList.EnterWriteLock();
                    CachedBidBooks = priceBook;
                    lockForList.ExitWriteLock();
                }
                else
                {
                    lockForList.EnterWriteLock();
                    CachedAskBooks = priceBook;
                    lockForList.ExitWriteLock();
                }
            }
            catch (ZmqException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

 public void ProcessData(object connection)
    {
        while (true)
        {
            priceBookData = ((ZeroMQClass)connection).GetPriceBook();
        }

    }

 public List<PriceBookData> GetPriceBook()
    {
        List<PriceBookData> AskAndBid = new List<PriceBookData>();
        lockForList.EnterWriteLock();
        if (CachedAskBooks != null && CachedBidBooks != null)
        {
            AskAndBid.Add(CachedBidBooks);
            AskAndBid.Add(CachedAskBooks);
            CachedBidBooks = null;
            CachedAskBooks = null;
            lockForList.ExitWriteLock();
            return AskAndBid;
        }
        lockForList.ExitWriteLock();
        return null;
    }
nsconnector
  • 838
  • 6
  • 12
dstew
  • 109
  • 1
  • 9
  • 1
    You need to provide code for both thread methods. – alex Mar 18 '13 at 16:23
  • No need to do this on your own threading to update the result. Use data binding to bind your view with data, and you just in th2, update your data source, and the UI thread will update the view automatically. – David Mar 18 '13 at 16:25
  • 1
    @David Nothing about the question is related to a UI. It's entirely dealing with accessing data and manipulating it *before it even gets to the UI layer*, assuming a UI layer even exists. – Servy Mar 18 '13 at 16:27
  • So what's the point of `ProcessData`? You just set the variable and never do any thing with it; so you're looping forever and never doing anything productive, by the look of it. – Servy Mar 18 '13 at 16:30
  • processdata calls a fucntion to put the pricebooks into a list so i can access them in my other class. the listen and getpricebook are in a sperate class than the process data. – dstew Mar 18 '13 at 16:31
  • ProcessData is a [tight loop](http://stackoverflow.com/questions/2212973/what-is-a-tight-loop) which holds the lock most of the time. A nasty quick fix could be to add a Thread.Sleep(100) call. If that works see if signaling the threads [WaitOne](http://msdn.microsoft.com/en-us/library/kzy257t0.aspx) works better. – rene Mar 18 '13 at 16:40

1 Answers1

4

What you have here is a producer-consumer model, but you aren't properly synchronizing them. The problem is that rather than some sort of buffer or collection of data that's ready to be processed, you have a single variable, and you completely synchronize access to that variable. This means that the producer can't ever be working while the consumer is working.

The BlockingCollection<T> is a fantastic class whenever dealing with producer/consumer queues.

var queue = new BlockingCollection<PriceBookData>();

Task.Factory.StartNew(() =>
{
    while (true)
    {
        byte[] zmqBuffer = new byte[102400];
        int messageLength;
        socket.Receive(zmqBuffer);
        byte[] message = new byte[messageLength];
        Buffer.BlockCopy(zmqBuffer, 0, message, 0, messageLength);
        PriceBookData priceBook = PriceBookData.CreateBuilder().MergeFrom(message).Build();
        double Type = priceBook.GetPb(0).QuoteType;
        queue.Add(priceBook);
    }
}, TaskCreationOptions.LongRunning);

Task.Factory.StartNew(() =>
{
    foreach (var item in queue.GetConsumingEnumerable())
    {
        //do stuff with item
    }
}, TaskCreationOptions.LongRunning);
Servy
  • 202,030
  • 26
  • 332
  • 449
  • Do you need some kind of loop in the first `StartNew`? As the code sits, won't it exit after one iteration? – chue x Mar 18 '13 at 16:38
  • so would this be done inside the listen function or would it be in place of the listen function? – dstew Mar 18 '13 at 16:43
  • @user1873594 This is in place of the entirety of the code that you've shown. You can (and probably should) refactor out the contents of the two tasks into other names methods (although in both cases it may make more sense to refactor out the body of the loop, rather than the whole thing. – Servy Mar 18 '13 at 16:45
  • @Servy Theres no way to just start the second thread a little bit after the first one? – dstew Mar 18 '13 at 17:24
  • @user1873594 Well, that's what it's already doing. The producer is started first. Granted, the time between them will likely be just a few microseconds, but it's some time. If you need to wait longer you certainly can, although since it'll just be waiting on the producer anyway I don't see any reason for that. – Servy Mar 18 '13 at 17:27
  • @Servy Well I need the pricebooks to be filled before the second thread starts. right now the second thread seems to stop the first thread from continuing at least when i debug it it does. – dstew Mar 18 '13 at 17:31
  • @user1873594 There were so many fundimental problems with your code that I'm not showing you how to fix it; I'm showing you how to replace what you've shown **in entirety** with something better that will work. – Servy Mar 18 '13 at 17:32