Mini Kabibi Habibi

Current Path : C:/Users/Public/Documents/DXperience 13.1 Demos/WinForms/CS/GridMainDemo/Modules/
Upload File :
Current File : C:/Users/Public/Documents/DXperience 13.1 Demos/WinForms/CS/GridMainDemo/Modules/RealTimeSource.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using DevExpress.Data;
using DevExpress.XtraCharts;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid.Columns;
using System.ComponentModel;
using DevExpress.Skins;

namespace DevExpress.XtraGrid.Demos {
    public partial class RealTimeSourceDemo : TutorialControl {
        ChangeThread chtr;
        Thread tr;
        //<gridControl1>
        RealTimeSource realTimeSource;
        //</gridControl1>

        Timer timerShow;
        Timer backgroundTimer;
        SynchronizationContext syncContext;
        readonly AutoResetEvent aEvent = new AutoResetEvent(true);
        readonly RepositoryItemProgressBar editorProgressBar;
        bool isHide = true;
        public RealTimeSourceDemo() {
            InitializeComponent();
            TutorialInfo.WhatsThisCodeFile = "CS\\GridMainDemo\\Modules\\RealTimeSource.cs";
            TutorialInfo.WhatsThisXMLFile = "DevExpress.XtraGrid.Demos.CodeInfo.RealTimeSource.xml";
            editorProgressBar = new RepositoryItemProgressBar { Minimum = 300, Maximum = 1000, ShowTitle = true, PercentView = false };
        }

        void RealTimeSourceDemo_Disposed(object sender, EventArgs e) {
            DoHide();
        }
        protected override void DoShow() {
            base.DoShow();
            isHide = false;
            syncContext = SynchronizationContext.Current;
            chtr = new ChangeThread(syncContext);
            trackBar1.Value = 10;
            PatchInterval();
            //<gridControl1>
            realTimeSource = CreateRealTimeSource();
            gridControl1.DataSource = realTimeSource;
            //</gridControl1>
            timerShow = new Timer(TimerShowCallback, null, 0, 500);
            backgroundTimer = new Timer(chtr.OnIdle, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(10));
            this.Disposed += RealTimeSourceDemo_Disposed;
            chartControl1.Series["UPSDiagram"].Points.Clear();
            tr = new Thread(chtr.Do);
            tr.IsBackground = true;
            tr.Start();
            //<gridControl1>
            realTimeSource.DataSource = chtr.List;
            //</gridControl1>
            gridView1.GridControl.RepositoryItems.AddRange(new RepositoryItem[] { editorProgressBar });
        }
        protected override void DoHide() {
            isHide = true;
            chtr.Stop();
            if(tr != null)
                tr.Join();
            backgroundTimer.Dispose();
            timerShow.Dispose();
            if(realTimeSource != null) {
                realTimeSource.DataSource = null;
                realTimeSource.Dispose();
            }
            base.DoHide();
        }

        static RealTimeSource CreateRealTimeSource() {
            RealTimeSource rts = new RealTimeSource();
            return rts;
        }

        private void TimerShowCallback(object state) {
            if(!aEvent.WaitOne(0) || isHide)
                return;
            double changes = chtr.ChangePerSecond;
            aEvent.Reset();
            syncContext.Post(x => {
                try {
                    double changePerSecond = (double)x;
                    if(chartControl1 != null && chartControl1.Series["UPSDiagram"] != null && chartControl1.Series["UPSDiagram"].Points != null) {
                        while(chartControl1.Series["UPSDiagram"].Points.Count >= 20) {
                            chartControl1.Series["UPSDiagram"].Points.RemoveAt(0);
                        }
                        chartControl1.Series["UPSDiagram"].Points.Add(new SeriesPoint(DateTime.Now.TimeOfDay.TotalSeconds, changePerSecond));
                    }
                } finally {
                    aEvent.Set();
                }
            }, changes);
        }

        private void UnplugRTS_Click(object sender, EventArgs e) {
            gridControl1.DataSource = null;
            if(!useRealtimeSource.Checked) {
                chtr.UseRealtimeSource = false;
                if(realTimeSource != null) {
                    realTimeSource.DataSource = null;
                    realTimeSource.Dispose();
                    realTimeSource = null;
                }
                gridControl1.DataSource = chtr.List;
            } else {
                realTimeSource = CreateRealTimeSource();
                realTimeSource.DataSource = chtr.List;
                gridControl1.DataSource = realTimeSource;
                chtr.UseRealtimeSource = true;
            }
            PatchInterval();
        }

        private void trackBar1_Scroll(object sender, EventArgs e) {
            PatchInterval();
        }
        void PatchInterval() {
            double pow = (this.trackBar1.Properties.Maximum - this.trackBar1.Value + 3) / 2.0;
            this.chtr.InterEventDelay = (int)Math.Pow(2.0, pow);
        }

        private void gridView1_DataSourceChanged(object sender, EventArgs e) {
            GridColumn column = gridView1.Columns["DayVal"];
            if(column == null || editorProgressBar == null)
                return;
            column.ColumnEdit = editorProgressBar;
        }

        private void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e) {
            double val = Convert.ToDouble(gridView1.GetRowCellValue(e.RowHandle, "ChgPercent"));
            if(val < 0)
                e.Appearance.ForeColor = CommonColors.GetCriticalColor(DevExpress.LookAndFeel.UserLookAndFeel.Default);
        }
    }
    public class ChangeThread {
        readonly BindingList<MarketData> collection = new BindingList<MarketData>();
        public IList List { get { return this.collection; } }
        private int interEventDelay = 1024000;
        public int InterEventDelay {
            set { Interlocked.Exchange(ref interEventDelay, value); }
        }
        int needStop;
        readonly Stopwatch sw;
        readonly Stopwatch backgroundSw = new Stopwatch();
        private bool useRealtimeSource = true;
        readonly SynchronizationContext context;
        int changesFromPriopChangePerSecond = 0;
        int priorChanges;
        object lockObj = new object();
        public bool UseRealtimeSource {
            set { lock(lockObj) useRealtimeSource = value; }
        }
        public int ChangePerSecond {
            get {
                if(Interlocked.CompareExchange(ref changesFromPriopChangePerSecond, 0, 0) == 0) {
                    return priorChanges;
                } else {
                    int changes = Interlocked.Exchange(ref changesFromPriopChangePerSecond, 0);
                    TimeSpan changeReportInterval = sw.Elapsed;
                    priorChanges = Convert.ToInt32(changes / changeReportInterval.TotalSeconds);
                    sw.Reset();
                    sw.Start();
                    return priorChanges;
                }
            }
        }
        public ChangeThread(SynchronizationContext context) {
            string[] data = new string[] {"ANR", "FE", "GT", "PRGO", "APD", "PPL", "AES", "AVB", "IBM", "GAS", "EFX", "GPC", "ICE", "IVZ", "KO", "CCE", "SO", "STI", 
                "BWA", "HRL", "WFM", "LM", "TROW", "K", "EXPE", "PCAR", "TRIP", "WHR", "WMT", "NU", "HST", "CVH", "LMT", "MAR", "CVC", "RF", "VMC", "PHM", "MU", "IRM", 
                "AMT", "BXP", "STT", "PBCT", "FISV", "BLL", "MTB", "DIS", "LH", "AKAM", "CPB", "MYL", "LIFE", "LEG", "SCG", "CNX", "COL", "MCHP", "GR", "DUK", "BAC", 
                "NUE", "UNM", "DLTR", "ABC", "TEG", "RRD", "EQR", "EXC", "BA", "CME", "NTRS", "VTR", "FITB", "PG", "KR", "M", "SNI", "ETN", "CLF", "PH", "KEY", "SHW", 
                "HD", "AFL", "TSS", "CMI", "HBAN", "AEP", "BIG", "LTD", "ESRX", "GLW", "WPI", "MON", "AAPL", "DF", "T", "CMA", "THC", "LUV", "TXN", "TIE", "PX"};

            this.sw = new Stopwatch();
            this.context = context;
            sw.Start();
            foreach(string name in data)
                collection.Add(new MarketData(name));
        }
        public void Do() {
            Random rndRow = new Random();
            int postedOperation = 0;
            do {

                Stopwatch watch = Stopwatch.StartNew();
                int row = rndRow.Next(0, collection.Count);
                lock(lockObj) {
                    if(!useRealtimeSource) {
                        Interlocked.Increment(ref postedOperation);
                        context.Post((x) => {
                            collection[row].Update();
                            collection.ResetItem(row);
                            Interlocked.Decrement(ref postedOperation);
                        }, null);
                    } else {
                        collection[row].Update();
                        collection.ResetItem(row);
                    }
                }
                this.changesFromPriopChangePerSecond++;
                for(; ; ) {
                    var elapsed = watch.ElapsedTicks;
                    var left = interEventDelay - elapsed;
                    if(left <= 0) {
                        if(!useRealtimeSource) {
                            Thread.Sleep(0);
                            while(backgroundSw.ElapsedMilliseconds > 12) {
                                if(Interlocked.CompareExchange(ref needStop, 0, 0) != 0)
                                    break;
                                Thread.Sleep(1);
                            }
                            if(Interlocked.CompareExchange(ref postedOperation, 0, 0) > 100) {
                                while(Interlocked.CompareExchange(ref postedOperation, 0, 0) > 10) {
                                    if(Interlocked.CompareExchange(ref needStop, 0, 0) != 0)
                                        break;
                                    Thread.Sleep(0);
                                }
                            }
                        }
                        break;
                    }
                    if(left > 20000)
                        Thread.Sleep(1);
                }
                watch.Stop();
            } while(Interlocked.CompareExchange(ref needStop, 0, 0) == 0);
        }
        public void Stop() {
            Interlocked.Exchange(ref needStop, 1);
        }
        public void OnIdle(object state) {
            context.Post((x) => { backgroundSw.Reset(); backgroundSw.Start(); }, null);
        }
    }

    public class MarketData {
        readonly static Random rnd = new Random();
        const double MAX = 950;
        const double MIN = 350;
        public string Ticker { get; private set; }
        double last;
        public double Last {
            get { return Math.Round(last, 1); }
            private set { last = value; }
        }
        double chgPercent;
        public double ChgPercent {
            get { return Math.Round(chgPercent * 100, 2); }
            private set { chgPercent = value; }
        }
        double open;
        public double Open {
            get { return Math.Round(open, 1); }
            private set { open = value; }
        }
        double high;
        public double High {
            get { return Math.Round(high, 1); }
            private set { high = value; }
        }
        double low;
        public double Low {
            get { return Math.Round(low, 1); }
            private set { low = value; }
        }
        public DateTime Date;
        public string Time {
            get { return Date.ToLongTimeString(); }
        }
        double dayVal;
        public double DayVal {
            get { return Math.Round(dayVal, 1); }
            private set { dayVal = value; }
        }

        public MarketData(string name) {
            Ticker = name;
            Open = (NextRnd() * (MAX - MIN)) + MIN;
            DayVal = open;
            UpdateInternal(Open);
        }
        public void Update() {
            double value = DayVal - (MAX - MIN) * 0.05 + NextRnd() * (MAX - MIN) * 0.1;
            if(value <= MIN)
                value = MIN;
            if(value >= MAX)
                value = MAX;
            UpdateInternal(value);
        }
        void UpdateInternal(double dayVal) {
            Last = DayVal;
            DayVal = dayVal;
            ChgPercent = (DayVal - Last) / DayVal;
            High = Math.Max(Open, Math.Max(DayVal, Last));
            Low = Math.Min(Open, Math.Min(DayVal, Last));
            this.Date = DateTime.Now;
        }
        double NextRnd() {
            double value = 0;
            for(int i = 0; i < 5; i++)
                value += rnd.NextDouble();
            return value / 5;
        }
    }

}