sending a message from one thread to another !!

Greetings...

I know it's an incredibly simple question but in C#  i just can't find how to do it... And the MSDN help system is giving a lot of information about everyting ...except the simple topic for which i need info on.

I have a main window that launches worker threads and i need to know when they finish their jobs... In addition to knowing when a working thread finishes, it must be capable of receiving some completion value. (i.e. A simple string)

Thanks !!!

 

Aco




Answer this question

sending a message from one thread to another !!

  • JeremyRooks

    You can solve that with some simple extra code:


    public class MyWorker
    {
     public event EventHandler Finished;
     
     public MyWorker()
     {
      // ...
     }
     
     public void Start()
     {
      Thread t = new Thread( new ThreadStart( Work ) );
      t.Start();
     }
     
     private void Work()
     {
      // Do some have long work.. work and work!
     
      // I'm finished, fire event!
      OnFinished();
     }
     
     protected void Finished()
     {
      if( Finished != null )
      {
       Control target = Finished.Target as Control;
      
       // Remove target.InvokeRequired when you always
       // want to invoke when it is posible.
       if( target != null && target.InvokeRequired )
       {
     target.Invoke( Finished, new object[] { this, EventArgs.Empty } );
       }
       else
       { 
     Finished( this, EventArgs.Empty );
       }
      }
     }
    }

     



  • Bimal Fernando

    Thanks "PJ. van de Sande" your post set me on the right direction !!!!

    For the record, i'd like to post back the modification so that your code sample could work ! 

    public partial class Form1 : Form

    {

        OnButton1_Click( ...)

        {

            Work w;

            Thread newThread;

            w = new Work();

            w.Finished += new Work.WorkerResultEventHandler(w_Finished);

            newThread = new Thread(w.DoWork);

            newThread.Start();

        }

        void w_Finished( object sender, WorkerResultEventArgs e )

        {

        // Worker was finished.

            MessageBox.Show( "Result is: " + e. Result );

        }

    }

    public class WorkerResultEventArgs : EventArgs

    {

        private string _result;

        public string Result

        {

            get

            {

                return _result;

            }

        }

        public WorkerResultEventArgs( string result )

        {

            _result = result;

        }

    }

    public class Work

    {

        public delegate void WorkerResultEventHandler( object sender, WorkerResultEventArgs e );

        public event WorkerResultEventHandler Finished;

        public void DoWork()

        {

            string str;

            // Do Some Work Here

            str = WorkResult(); // A string value that will change from thread to thread.

            WorkerResultEventArgs e = new WorkerResultEventArgs( str );

            OnFinished( this, e );

        }

    }



  • SPC Posson

     I should have pointed-out that the thread is in its own class...

    The thread in the "Work" class must return its completion state to the parent caller. In regular C++, i would have done this by using a message loop in the parent calling class and i would simply have the working thread send its completion state as a simple window message.

    public partial class Form1 : Form

    {

        OnButton1_Click( ...)

        {

            Work w;

            Thread newThread;

            w = new Work();

            newThread = new Thread(w.DoWork);

            newThread.Start();

        }

    }

    public class Work

    {

        public void DoWork()

        {

            string str;

            // Do Some Work Here

            str = WorkResult();  // A string value that will change from thread to thread.

            SendMessageToParentClass (str); // Here is the message i need to send before ending the thread.

        }

    }

    I don't think that the solution proposed so far can fit with the situation described above.... (Again, My mistake !)

    Thanks for any help !

    Acoquinar



  • Larry Joy

    You can give your worker class an Finished event, for example:


    public class MyWorker
    {
     public event EventHandler Finished;
     
     public MyWorker()
     {
      // ...
     }
     
     public void Start()
     {
      Thread t = new Thread( new ThreadStart( Work ) );
      t.Start();
     }
     
     private void Work()
     {
      // Do some have long work.. work and work!
      
      // I'm finished, fire event!
      OnFinished();
     }
     
     protected void Finished()
     {
      if( Finished != null )
      {
       Finished( this, EventArgs.Empty );
      }
     }
    }

     


    Now just wire the event in the class where you start the workers and want to get a notice when one is finished.

    I hope you understand it, please tell me when you don't.

  • pubs

    Neither of the replies so far have actually addressed the issue of getting the result back to the UI thread, which is where you'll have to have it if you want the UI to change.

    See http://www.pobox.com/~skeet/csharp/threads/winforms.shtml for details on this kind of thing.

    Jon



  • ravievg

    Another way to do it is through delegates. It's very similar to Events, but you can declare any method signature to be a delegate. Either way would work for what you want though.

  • Pham Thanh Tuan

    You still can create an Finished event, here is some source i wrote it out of the head, so there can be some errors in it.


    public partial class Form1 : Form
    {
        OnButton1_Click( ...)
        {
            Work w;

            Thread newThread;

            w = new Work();
            w.Finished += new EventHandler( w_Finished );

            newThread = new Thread(w.DoWork);

            newThread.Start();

        }
       
        private void w_Finished( object sender, WorkerResultEventArgs e )
        {
            // Worker was finished.
            MessageBox.Show( "Result is: " + e. Result );
        }
    }

    public delegate void WorkerResultEventArgs( object sender, WorkerResultEventArgs e );

    public class WorkerResultEventArgs : EventArgs
    {
        private string _result;
        public string Result
        {
            get
            {
                return _result;
            }
        }
       
        public WorkerResultEventArgs( string result )
        {
            _return = result;
        }
    }

    public class Work
    {
        public event WorkerResultEventArgs Finished;

        public void DoWork()
        {
            string str;

            // Do Some Work Here

            str = WorkResult();  // A string value that will change from thread to thread.

            WorkerResultEventArgs e = new WorkerResultEventArgs( str );
            OnFinished( e );
        }
       
        protected void OnFinished(WorkerResultEventArgs e)
        {
            if( Finished != null )
            {
                Control target = Finished.Target as Control;

                // Remove target.InvokeRequired when you always
                // want to invoke when it is posible.
                if( target != null && target.InvokeRequired )
                {
                    target.Invoke( Finished, new object[] { this, e } );
                }
                else
                {
                    Finished( this, e );
                }
            }
        }
    }

     



  • sending a message from one thread to another !!