Thread: looking for an example (MVC + multithreading)

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    39

    "Parameter count mismatch" error in MVC + multithreading example

    --- SOLVED ---

    original post:

    I'm looking for a c# example that shows multithreading and MVC combined.

    for example: a form with two counters counting up from 0 to 100 with thread1 increasing counter1 every 100ms and thread2 increasing counter2 every 150ms.

    I know the MVC pattern and I'm familiar with multithreading but I haven't worked with them alot so I'd really appreciate a simple example to show me the basic setup.

    thx in advance!
    Progress:

    I wrote an example code for the proposed example but can't get it to work. As sugested I used a cross thread controler to fix the thread access problem. Now I get a different error though:
    "Parameter count mismatch." on line "Application.Run(new Form1());"


    current code:
    program.cs
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    Form1.cs:
    Code:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form, TView
        {
            TModel model = new TModel();
            private TControler controler;
    
            public Form1()
            {
                InitializeComponent();
    
                model.addView(this);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //setup 2 threads that work to increase counters
                TControler cont = new TControler(model);
                cont.setStep(400);
                Thread thread = new Thread(new ThreadStart(cont.runme));
                thread.Name = "first";
                thread.Start();
    
                TControler cont2 = new TControler(model);
                cont2.setCounter(2);
                cont2.setStep(500);
                Thread thread2 = new Thread(new ThreadStart(cont2.runme));
                thread2.Name = "second";
                thread2.Start();
    
    
            }
            private delegate void CrossThreadLabelHandler(Label obj, String str);
            private void UpdateLabelText(Label obj, String str)
            {
                try
                {
                    if (obj.InvokeRequired)
                        obj.BeginInvoke(new CrossThreadLabelHandler(this.UpdateLabelText), str);
                    else
                        obj.Text = str;
                }
                catch(Exception e)
                {
                    Console.Out.WriteLine("Exception: "+e);
                }
            }
    
            public void doUpdate()
            {
    
                UpdateLabelText(label1, model.getC1().ToString());
                UpdateLabelText(label2, model.getC2().ToString());
            }
        }
    
        public interface aModel
        {
            void addView(TView v);
            void removeView(TView v);
            void notifyListeners();
        }
        public class TModel : aModel
        {
            private int c1 = 0;
            private int c2 = 0;
    
            public void increase1()
            {
                c1++;
                notifyListeners();
            }
            public void increase2()
            {
                c2++;
                notifyListeners();
            }
            public int getC1()
            {
                return c1;
            }
            public int getC2()
            {
                return c2;
            }
            
    
            ArrayList l=new ArrayList();
            public void addView(TView v)
            {
                l.Add(v);
            }
    
            public void removeView(TView v)
            {
                l.Remove(v);
            }
    
            public void notifyListeners()
            {
                foreach(TView v in l)
                {
                    v.doUpdate();
                }
            }
        }
    
        public interface TView
        {
            void doUpdate();
        }
    
        public interface aControler
        {
        }
        public class TControler: aControler
        {
            private TModel model;
            private volatile bool run;
            private int step=100;
            private int counter = 1;
    
            internal TControler(TModel m)
            {
                model=m;
                run = true;
            }
            public void setStep(int ms)
            {
                step = ms;
            }
            public void setCounter(int c)
            {
                counter = c;
            }
    
            public void runme()
            {
                while(run)
                {
                    if(counter==1)
                        model.increase1();
                    else
                        model.increase2();
                    Thread.Sleep(step);
                }
            }
        }
    }
    Last edited by klmdb; 02-11-2011 at 06:06 AM. Reason: updating

  2. #2
    Registered User
    Join Date
    Dec 2009
    Posts
    39
    PS this is an example I built, but it doesn't work. My debugger says"Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on."

    Any clues on how to fix this?

    Code:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form, TView
        {
            TModel model = new TModel();
            private TControler controler;
    
            public Form1()
            {
                InitializeComponent();
    
                model.addView(this);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //setup 2 threads that work to increase counters
                TControler cont = new TControler(model);
                Thread thread = new Thread(new ThreadStart(cont.runme));
                thread.Name = "first";
                thread.Start();
    
                TControler cont2 = new TControler(model);
                cont2.setCounter(2);
                cont2.setStep(150);
                Thread thread2 = new Thread(new ThreadStart(cont2.runme));
                thread2.Name = "second";
                thread2.Start();
    
    
            }
    
            public void doUpdate()
            {
                label1.Text = model.getC1().ToString();
                label2.Text = model.getC2().ToString();
            }
        }
    
        public interface aModel
        {
            void addView(TView v);
            void removeView(TView v);
            void notifyListeners();
        }
        public class TModel : aModel
        {
            private int c1 = 0;
            private int c2 = 0;
    
            public void increase1()
            {
                c1++;
                notifyListeners();
            }
            public void increase2()
            {
                c2++;
                notifyListeners();
            }
            public int getC1()
            {
                return c1;
            }
            public int getC2()
            {
                return c2;
            }
            
    
            ArrayList l=new ArrayList();
            public void addView(TView v)
            {
                l.Add(v);
            }
    
            public void removeView(TView v)
            {
                l.Remove(v);
            }
    
            public void notifyListeners()
            {
                foreach(TView v in l)
                {
                    v.doUpdate();
                }
            }
        }
    
        public interface TView
        {
            void doUpdate();
        }
    
        public interface aControler
        {
        }
        public class TControler: aControler
        {
            private TModel model;
            private volatile bool run;
            private int step=100;
            private int counter = 1;
    
            internal TControler(TModel m)
            {
                model=m;
                run = true;
            }
            public void setStep(int ms)
            {
                step = ms;
            }
            public void setCounter(int c)
            {
                counter = c;
            }
    
            public void runme()
            {
                while(run)
                {
                    if(counter==1)
                        model.increase1();
                    else
                        model.increase2();
                    Thread.Sleep(step);
                }
            }
        }
    }

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I don't have any experience with the MVC pattern, but check out the Control.InvokeRequired property (and of course the Control.Invoke() method) to use controls from a different thread.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    The problem is you can't update GUI controls outside the GUI (main) thread. So this...

    Code:
    label1.Text = "test";
    ...will throw the exception you're receiving.

    The way around it is to call the Invoke() or BeginInvoke() methods contained within the label controls. So you'd create a method, eg...

    Code:
    private delegate void CrossThreadLabelHandler(Label obj, String str);
    private void UpdateLabelText(Label obj, String str)
    {
        if (obj.InvokeRequired)
            obj.BeginInvoke(new CrossThreadLabelHandler(this.UpdateLabelText), str);
        else
            obj.Text = str;
    }
    ...and then use that method to access the GUI thread from your worker thread.

    Code:
    label1.Text = "test"; // doesn't work from a different thread!!
    UpdateLabelText(label1, "test"); // this will work.

  5. #5
    Registered User
    Join Date
    Dec 2009
    Posts
    39
    I updated my code:
    Code:
            private delegate void CrossThreadLabelHandler(Label obj, String str);
            private void UpdateLabelText(Label obj, String str)
            {
                if (obj.InvokeRequired)
                    obj.BeginInvoke(new CrossThreadLabelHandler(this.UpdateLabelText), str);
                else
                    obj.Text = str;
            }
    
            public void doUpdate()
            {
    
                UpdateLabelText(label1, model.getC1().ToString());
                UpdateLabelText(label2, model.getC2().ToString());
            }

    but now I get this error: "Parameter count mismatch." on line "Application.Run(new Form1());"

  6. #6
    Registered User
    Join Date
    Dec 2009
    Posts
    39
    I found the bug! I modified the supplied delegate/invoke code to this:
    Code:
            private delegate void CrossThreadLabelHandler(Label obj, String str);
            private void UpdateLabelText(Label obj, String str)
            {
                try
                {
                    CrossThreadLabelHandler ch = new CrossThreadLabelHandler(this.UpdateLabelText);
                    if (obj.InvokeRequired)
                        obj.BeginInvoke(ch, obj, str);
                    else
                        obj.Text = str;
                }catch(Exception e)
                {
                    Console.Out.WriteLine("Exception: "+e);
                }
            }

  7. #7
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    Oops, sorry about that. Tired eyes is my excuse lol.

    Code:
    obj.BeginInvoke(new CrossThreadLabelHandler(this.UpdateLabelText), obj, str);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multithreading Madness?
    By leeor_net in forum Game Programming
    Replies: 4
    Last Post: 09-11-2009, 12:46 AM
  2. [Hardware + Software][C++ or C#] USB Fan
    By Mywk in forum C++ Programming
    Replies: 16
    Last Post: 07-04-2009, 03:12 PM
  3. What is the fan size?
    By adr in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 12-06-2007, 03:21 PM
  4. Computer Fan question
    By the dead tree in forum Tech Board
    Replies: 2
    Last Post: 12-28-2005, 04:16 PM
  5. P4 Fan problem: Urgent
    By RoD in forum Tech Board
    Replies: 5
    Last Post: 01-15-2003, 12:12 PM