Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Threading and cross-threading

Threading and cross-threading

Scheduled Pinned Locked Moved C#
questiondesignhelp
5 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O Offline
    O Offline
    oceanexplorer
    wrote on last edited by
    #1

    Hi, I have created a windows form the contains a button and a list box. When the button is clicked it fires the following code, Migration.Begin(); thread = new Thread(new ThreadStart(Migration.Begin)); thread.Start(); Migration is a seperate class that is executed on a new thread as it will be a labour intensive task and I want the UI to remain usable. However within the migration module I want to be able to call back to the thread that created the UI and have it append a message to the listbox. So intially in the UI class I added a delgate which called a seperate function to add a line to the listbox: public static LoggerListDelegate loggerListDelegate; public Logger() { InitializeComponent(); loggerListDelegate = new LoggerListDelegate(AddLine); } And the function addline was as follows: public void AddLine(string line) { lstLogger.Items.Add(DateTime.Now.ToLongTimeString() + ": " + line); } I then called this from the Migration using the following: Logger.loggerListDelegate.BeginInvoke("******Migration has begun******",null,null); This however is giving me an issue that it is not thread safe as I am trying to invoke on different thread the list was created on. So my understanding is that I would really need to call the Listbox invoke method, e.g. lstLogger.Invoke(delegate, objects) If that's correct how do I access the lstLogger from my Migration class in order to invoke it? If this is not right how do I go about making it threadsafe? Many many many thanks Paul

    D O L 3 Replies Last reply
    0
    • O oceanexplorer

      Hi, I have created a windows form the contains a button and a list box. When the button is clicked it fires the following code, Migration.Begin(); thread = new Thread(new ThreadStart(Migration.Begin)); thread.Start(); Migration is a seperate class that is executed on a new thread as it will be a labour intensive task and I want the UI to remain usable. However within the migration module I want to be able to call back to the thread that created the UI and have it append a message to the listbox. So intially in the UI class I added a delgate which called a seperate function to add a line to the listbox: public static LoggerListDelegate loggerListDelegate; public Logger() { InitializeComponent(); loggerListDelegate = new LoggerListDelegate(AddLine); } And the function addline was as follows: public void AddLine(string line) { lstLogger.Items.Add(DateTime.Now.ToLongTimeString() + ": " + line); } I then called this from the Migration using the following: Logger.loggerListDelegate.BeginInvoke("******Migration has begun******",null,null); This however is giving me an issue that it is not thread safe as I am trying to invoke on different thread the list was created on. So my understanding is that I would really need to call the Listbox invoke method, e.g. lstLogger.Invoke(delegate, objects) If that's correct how do I access the lstLogger from my Migration class in order to invoke it? If this is not right how do I go about making it threadsafe? Many many many thanks Paul

      D Offline
      D Offline
      Daniel Grunwald
      wrote on last edited by
      #2

      There is a huge difference between Control.BeginInvoke and Delegate.BeginInvoke: Delegate.BeginInvoke will call the method on a thread from the ThreadPool, but Control.BeginInvoke will call the method on the thread that runs the message loop for that control (which usually is the main thread). Since the main thread created the form and the controls on it, it is the only thread allowed to access the controls. So you have to use Control.BeginInvoke (lstLogger.BeginInvoke or this.BeginInvoke if "this" is a form).

      O 1 Reply Last reply
      0
      • D Daniel Grunwald

        There is a huge difference between Control.BeginInvoke and Delegate.BeginInvoke: Delegate.BeginInvoke will call the method on a thread from the ThreadPool, but Control.BeginInvoke will call the method on the thread that runs the message loop for that control (which usually is the main thread). Since the main thread created the form and the controls on it, it is the only thread allowed to access the controls. So you have to use Control.BeginInvoke (lstLogger.BeginInvoke or this.BeginInvoke if "this" is a form).

        O Offline
        O Offline
        oceanexplorer
        wrote on last edited by
        #3

        Hey Daniel, thanks for a great response, that makes it a lot clearer for me, I was having major mental block! I have just one further question, what is the best way for me to access the lstLogger control from a seperate class? I tried changing the control to public static but the obviously is incorrect. I could in the migration class create a new instance of the Logger class and call it- Logger log = new Logger(); log.lstLogger.BeginInvoke(delegate, objects) But that won't work properly, what are you thoughts? Thanks again Paul

        1 Reply Last reply
        0
        • O oceanexplorer

          Hi, I have created a windows form the contains a button and a list box. When the button is clicked it fires the following code, Migration.Begin(); thread = new Thread(new ThreadStart(Migration.Begin)); thread.Start(); Migration is a seperate class that is executed on a new thread as it will be a labour intensive task and I want the UI to remain usable. However within the migration module I want to be able to call back to the thread that created the UI and have it append a message to the listbox. So intially in the UI class I added a delgate which called a seperate function to add a line to the listbox: public static LoggerListDelegate loggerListDelegate; public Logger() { InitializeComponent(); loggerListDelegate = new LoggerListDelegate(AddLine); } And the function addline was as follows: public void AddLine(string line) { lstLogger.Items.Add(DateTime.Now.ToLongTimeString() + ": " + line); } I then called this from the Migration using the following: Logger.loggerListDelegate.BeginInvoke("******Migration has begun******",null,null); This however is giving me an issue that it is not thread safe as I am trying to invoke on different thread the list was created on. So my understanding is that I would really need to call the Listbox invoke method, e.g. lstLogger.Invoke(delegate, objects) If that's correct how do I access the lstLogger from my Migration class in order to invoke it? If this is not right how do I go about making it threadsafe? Many many many thanks Paul

          O Offline
          O Offline
          oceanexplorer
          wrote on last edited by
          #4

          Can anyone still answer this?

          1 Reply Last reply
          0
          • O oceanexplorer

            Hi, I have created a windows form the contains a button and a list box. When the button is clicked it fires the following code, Migration.Begin(); thread = new Thread(new ThreadStart(Migration.Begin)); thread.Start(); Migration is a seperate class that is executed on a new thread as it will be a labour intensive task and I want the UI to remain usable. However within the migration module I want to be able to call back to the thread that created the UI and have it append a message to the listbox. So intially in the UI class I added a delgate which called a seperate function to add a line to the listbox: public static LoggerListDelegate loggerListDelegate; public Logger() { InitializeComponent(); loggerListDelegate = new LoggerListDelegate(AddLine); } And the function addline was as follows: public void AddLine(string line) { lstLogger.Items.Add(DateTime.Now.ToLongTimeString() + ": " + line); } I then called this from the Migration using the following: Logger.loggerListDelegate.BeginInvoke("******Migration has begun******",null,null); This however is giving me an issue that it is not thread safe as I am trying to invoke on different thread the list was created on. So my understanding is that I would really need to call the Listbox invoke method, e.g. lstLogger.Invoke(delegate, objects) If that's correct how do I access the lstLogger from my Migration class in order to invoke it? If this is not right how do I go about making it threadsafe? Many many many thanks Paul

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Hi I would do the following: let's say you have 2 classes the worker class Worker and the Main Form frmMain

            public class Worker
            {
            public event EventHandler MyInterThreadEvent;
            public Worker()
            {
            // do something here
            }
            protected virtual void onMyInterThreadEvent(EventArgs e)
            {
            if (MyInterThreadEvent != null)
            {
            MyInterThreadEvent(this, e);
            }
            }
            public void ThreadMethod()
            {
            do
            {
            // do something here
            onMyInterThreadEvent(EventArgs.Empty);
            }while(something);
            }
            }
            public class frmMain:Form
            {
            private Worker MyPersonalSlave;
            // .. All the Form - Stuff coming here...
            public frmMain()
            {
            InitializeComponent();
            MyPersonalSlave = new Worker();
            MyPersonalSlave.MyInterThreadEvent += new EventHandler(MyPersonalSlave_MyInterThreadEvent);
            // start a thread here that makes you worker work.
            }
            private void MyPersonalSlave_MyInterThreadEvent(object sender, EventArgs e)
            {
            if (!InvokeRequired) // are we in the correct Thread?
            {
            // do what ever you want to do when the event gets fired
            }
            else // use the invoke on the form to run this method in the correct Thread
            {
            Invoke(new EventHandler(MyPersonalSlave_MyInterThreadEvent),new object[]{sender,e});
            }
            }
            }

            Greets m@u

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups