Click here to Skip to main content
15,890,845 members
Home / Discussions / .NET (Core and Framework)
   

.NET (Core and Framework)

 
GeneralRe: Crossing the UI sync context with a datasource Pin
Eddy Vluggen9-Aug-12 21:08
professionalEddy Vluggen9-Aug-12 21:08 
AnswerRe: Crossing the UI sync context with a datasource Pin
JoeRip9-Aug-12 10:29
JoeRip9-Aug-12 10:29 
GeneralRe: Crossing the UI sync context with a datasource Pin
Ed Hill _5_9-Aug-12 22:45
Ed Hill _5_9-Aug-12 22:45 
GeneralRe: Crossing the UI sync context with a datasource Pin
Eddy Vluggen9-Aug-12 23:01
professionalEddy Vluggen9-Aug-12 23:01 
GeneralRe: Crossing the UI sync context with a datasource Pin
JoeRip9-Aug-12 23:46
JoeRip9-Aug-12 23:46 
GeneralRe: Crossing the UI sync context with a datasource Pin
JoeRip10-Aug-12 16:16
JoeRip10-Aug-12 16:16 
GeneralRe: Crossing the UI sync context with a datasource Pin
Ed Hill _5_11-Aug-12 6:14
Ed Hill _5_11-Aug-12 6:14 
GeneralRe: Crossing the UI sync context with a datasource Pin
JoeRip10-Aug-12 18:47
JoeRip10-Aug-12 18:47 
Well, it works. Not sure about design quality, but it was better than the hacks I was using before. Thanks for all the help! Let me know if it sucks. Here's a sample which demonstrates the pattern; first the caller/form:
using System;
using System.Windows.Forms;
using GrowingDataTable;

namespace dgv
{
    public partial class Form1 : Form
    {
        public DataGridView dgvMain;
        public delegate void delEventHandler(object sender,
               GrowingDataTable.UpdateDataTableOnYourThreadContextEventArgs e);
        public GrowingDataTable gt;
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // add a datagridview to the form
            dgvMain = new DataGridView();
            Controls.Add(dgvMain);
            dgvMain.Dock = System.Windows.Forms.DockStyle.Fill;

            // create the GrowingTable object
            gt = new GrowingDataTable();

            // subscribe to the GrowingTable event
            gt.RaiseUpdateTableAgainstYourThreadContextEvent += new 
           EventHandler<GrowingDataTable.UpdateDataTableOnYourThreadContextEventArgs>
          (gt_RaiseUpdateTableAgainstYourThreadContextEvent);

            // tell gt that we want to be updated
            gt.UpdateDataTableOnCallerThreadContext = true;

            // assign the DataTable as DataSource for our datagridview
            dgvMain.DataSource = gt.itemTable;
            
            // tell the GrowingTable to start growing; 
            // delay start for 3 seconds, add row every 1 second
            gt.Start(3000, 1000);
        }

        void gt_RaiseUpdateTableAgainstYourThreadContextEvent(object sender,
                GrowingDataTable.UpdateDataTableOnYourThreadContextEventArgs e)
        {
            if (InvokeRequired) {
                Invoke(new
                delEventHandler(gt_RaiseUpdateTableAgainstYourThreadContextEvent),
                new object[] { sender, e}); }
            else
            {
                if ((e.Updates != null) || (e.Updates.Count > 0))
                {
                    gt.UpdateTableOnMyThreadContext(e.Updates);
                }
            }
        }
    }
}

Then the library class GrowingDataTable:
using System;
using System.Collections.Concurrent;

namespace GrowingDataTable
{
    public class GrowingDataTable
    {
        public System.Data.DataTable itemTable;
        public System.Threading.Timer myTimer = null;
        private ConcurrentQueue<System.Data.DataRow> qUpdates = new
                ConcurrentQueue<System.Data.DataRow>();

        // constructor
        public GrowingDataTable()
        {
            // table and timer
            itemTable = new System.Data.DataTable();
            myTimer = new System.Threading.Timer(this.AddRows, null, 
                  System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);

            // add some columns to table
            for (int i = 0; i < 10; i++) {
                itemTable.Columns.Add(new System.Data.DataColumn
                       (i.ToString(), typeof(System.DateTime))); }
        }

        // Property which specifies that the caller needs table updates
        // to occur on their own thread context.
        public bool UpdateDataTableOnCallerThreadContext { get; set; }

        // Class which describes the custom event arguments raised
        public class UpdateDataTableOnYourThreadContextEventArgs : EventArgs
        {
            private ConcurrentQueue<System.Data.DataRow> qu;

            public UpdateDataTableOnYourThreadContextEventArgs
                       (ConcurrentQueue<System.Data.DataRow> Qu)
            {
                qu = Qu;
            }

            public ConcurrentQueue<System.Data.DataRow> Updates
            {
                get { return qu; }
            }
        }

        // Event raised when we need to update our data, and customer has specified
        // they need the update to occur on their own thread context (eg, UX thread).
        public event EventHandler<UpdateDataTableOnYourThreadContextEventArgs>
                                      RaiseUpdateTableAgainstYourThreadContextEvent;

        public void UpdateTableOnMyThreadContext(
                         ConcurrentQueue<System.Data.DataRow> Q)
        {
            System.Data.DataRow dr = null;
            while (Q.TryDequeue(out dr))
            {
                if (dr != null)
                {
                    itemTable.Rows.Add(dr);
                }
            }
        }

        public void Start(int delay, int interval)
        {
            myTimer.Change(delay, interval);
        }

        private void AddRows(object state)
        {
            if (itemTable.Rows.Count < 10)
            {
                System.Data.DataRow dr = this.itemTable.NewRow();

                // fill row with pseudo data
                for (int i = 0; i < 11; i++) { dr[i.ToString()] = DateTime.Now; }

                // If caller has specified, notify them so they can update the
                // data on their own thread context.
                if (UpdateDataTableOnCallerThreadContext)
                {
                    // add row to qUpdates, raise the event
                    qUpdates.Enqueue(dr);
                    OnRaiseUpdateDataTableAgainstYourThreadContextEvent(new
                             UpdateDataTableOnYourThreadContextEventArgs(qUpdates));
                }
                else
                {
                    this.itemTable.Rows.Add(dr);
                }
            }
            else
            {
                myTimer.Dispose();
                myTimer = null;
            }
        }

        protected virtual void OnRaiseUpdateDataTableAgainstYourThreadContextEvent(
                                     UpdateDataTableOnYourThreadContextEventArgs q)
        {
            // protect against race conditions:
            EventHandler<UpdateDataTableOnYourThreadContextEventArgs> handler =
                                     RaiseUpdateTableAgainstYourThreadContextEvent;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                handler(this, q);
            }
        }
    }

}

QuestionIf proccess is running then start coding ! Help Needed Pin
jitforce25858-Aug-12 8:09
jitforce25858-Aug-12 8:09 
AnswerRe: If proccess is running then start coding ! Help Needed Pin
jitforce25858-Aug-12 8:58
jitforce25858-Aug-12 8:58 
QuestionA Way Capturing Straight the Active Windows Only ?? Pin
jitforce25858-Aug-12 4:30
jitforce25858-Aug-12 4:30 
AnswerRe: A Way Capturing Straight the Active Windows Only ?? Pin
Pete O'Hanlon8-Aug-12 4:48
mvePete O'Hanlon8-Aug-12 4:48 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
jitforce25858-Aug-12 5:05
jitforce25858-Aug-12 5:05 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
Pete O'Hanlon8-Aug-12 5:10
mvePete O'Hanlon8-Aug-12 5:10 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
jitforce25858-Aug-12 5:34
jitforce25858-Aug-12 5:34 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
jitforce25858-Aug-12 6:10
jitforce25858-Aug-12 6:10 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
Pete O'Hanlon8-Aug-12 7:28
mvePete O'Hanlon8-Aug-12 7:28 
GeneralRe: A Way Capturing Straight the Active Windows Only ?? Pin
jitforce25858-Aug-12 8:07
jitforce25858-Aug-12 8:07 
Question.net framework 4 takes much time than 2.0. Why? Pin
ruby_e_s8-Aug-12 2:26
ruby_e_s8-Aug-12 2:26 
AnswerRe: .net framework 4 takes much time than 2.0. Why? Pin
Pete O'Hanlon8-Aug-12 2:47
mvePete O'Hanlon8-Aug-12 2:47 
GeneralRe: .net framework 4 takes much time than 2.0. Why? Pin
ruby_e_s8-Aug-12 21:28
ruby_e_s8-Aug-12 21:28 
GeneralRe: .net framework 4 takes much time than 2.0. Why? Pin
Pete O'Hanlon8-Aug-12 23:19
mvePete O'Hanlon8-Aug-12 23:19 
GeneralRe: .net framework 4 takes much time than 2.0. Why? Pin
ruby_e_s8-Aug-12 23:36
ruby_e_s8-Aug-12 23:36 
GeneralRe: .net framework 4 takes much time than 2.0. Why? Pin
Pete O'Hanlon8-Aug-12 23:48
mvePete O'Hanlon8-Aug-12 23:48 
GeneralRe: .net framework 4 takes much time than 2.0. Why? Pin
ruby_e_s9-Aug-12 0:01
ruby_e_s9-Aug-12 0:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.