Click here to Skip to main content
15,886,795 members
Articles / Programming Languages / C#

AFP: Almost Functional Programming in C#: Part 2

Rate me:
Please Sign up or sign in to vote.
4.89/5 (4 votes)
6 Mar 2013CPOL20 min read 17.5K   142   12  
Putting the programming style to the test by using it in a multi-threaded server.
using System;
using System.Collections.Generic;
using System.Threading;

namespace StockTest
{
    public class FakeConnection
    {
        class RandomPrice
        {
            public readonly string StockId;
            Random _rnd;
            double _price;

            public RandomPrice(string stockId)
            {
                StockId = stockId;
                _rnd = new Random();
                _price = 50.0;
            }

            public PriceUpdate GenerateFakePriceUpdate()
            {
                int direction = _rnd.Next(3);
                switch (direction) {
                    case 0:
                        _price = Math.Round(Math.Max(_price - 0.1, 10.0), 1);
                        break;
                    case 1:
                        _price = Math.Round(Math.Min(_price + 0.1, 100.0), 1);
                        break;
                }
                return new PriceUpdate(StockId, _price * 0.9, _price);
            }
        }

        List<RandomPrice> _fakeConnections = new List<RandomPrice>();
        Action<PriceUpdate> _callback;
        Thread _thread;
        volatile bool _stop;

        public void Start(Action<PriceUpdate> callback)
        {
            _callback = callback;
            _thread = new Thread(ThreadProc);
            _thread.Start();
        }

        public void Stop()
        {
            if (_thread != null) {
                _stop = true;
                _thread.Join();
            }
        }

        void ThreadProc()
        {
            var rnd = new Random();
            while (!_stop) {
                try {
                    var update = new PriceUpdate();
                    bool updateExists = false;
                    lock (_fakeConnections) {
                        if (_fakeConnections.Count > 0) {
                            var stock = _fakeConnections[rnd.Next(_fakeConnections.Count)];
                            update = stock.GenerateFakePriceUpdate();
                            updateExists = true;
                        }
                    }
                    if (updateExists)
                        _callback(update);
                } catch (Exception ex) {
                    Console.WriteLine("FakeConnection callback failed: {0}", ex.Message);
                }
                Thread.Sleep(100);
            }
        }

        public void Subscribe(string stockId)
        {
            lock (_fakeConnections) {
                _fakeConnections.Add(new RandomPrice(stockId));
            }
        }

        public void Unsubscribe(string stockId)
        {
            lock (_fakeConnections) {
                _fakeConnections.RemoveAll(x => x.StockId == stockId);
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
New Zealand New Zealand
I am a senior software developer with almost 20 years of experience. I have extensive knowledge of C#, C++ and Assembly languages, working mainly on Windows and embedded systems. Outside of work I am interested in a wider variety of technologies, including learning 20 programming languages, developing Linux kernel drivers or advocating Functional Programming recently.

Comments and Discussions