locked
How to return a value from thread calling method?

    Question

  •  

    Hi,

     

    I am running a method in thread. i.e. I am using threadpool and creating a new thread using that method. I can pass one parameter to this method. But I cannot get anything in return unless I use static variable and change its value in that function.

    Can I achieve the same functionality without using static variable? Is there a way to receive return from a method used in threading?

     

    Thanks.

    Wednesday, October 03, 2007 10:13 PM

Answers

  • You can use the ThreadPool.QueueUserWorkItem to asynchronously invoke code.  The WaitCallback delegate will be called with the given state, which can include a reference for the "result" of code. For example:

    Code Block

    class MyClass

    {

        private class State

        {

            public EventWaitHandle eventWaitHandle = new ManualResetEvent(false);

            public int result;

            public object parameters[];

        }

        private static void PerformUserWorkItem( Object stateObject )

        {

            State state = stateObject as State;

            if(state != null)

            {

                // do something lengthy with state.parameters...

                state.result = 42;

                state.eventWaitHandle.Set(); // signal we're done

            }

        }

        public static object DoWorkSynchronous()

        {

            State state = new State();

            ThreadPool.QueueUserWorkItem(PerformUserWorkItem, state);

            state.eventWaitHandle.WaitOne();

            Console.WriteLine(state.result);

            return state.result;

        }

    }

     

     

     

     

     

    Thursday, October 04, 2007 7:14 PM
    Moderator
  • Threads do not have the concept of "return value" because threads run asynchronously.

     

    One technique that you might find helpful is to store the result in a field in the same class that contains the thread's main method.  This will work well if you instantiate a new instance of that class every time you create that kind of thread (which is a good practice).

     

    For example, in your class you could define a Start() method that creates a new Thread object using a private thread start procedure declared in that same class.  Store a reference to that Thread object in a private field in the class (let's call it _MyThread).  At the end of the thread procedure, set another private field (let's call it _ReturnValue).  Define a ReturnValue property that returns the value in _ReturnValue.

     

    Often, your class will need methods to query the status of the thread such as: WaitForCompletion -- call _MyThread.Join.  IsStillRunning -- call _MyThread.IsAlive.

    Thursday, October 04, 2007 12:36 AM

All replies

  • Threads do not have the concept of "return value" because threads run asynchronously.

     

    One technique that you might find helpful is to store the result in a field in the same class that contains the thread's main method.  This will work well if you instantiate a new instance of that class every time you create that kind of thread (which is a good practice).

     

    For example, in your class you could define a Start() method that creates a new Thread object using a private thread start procedure declared in that same class.  Store a reference to that Thread object in a private field in the class (let's call it _MyThread).  At the end of the thread procedure, set another private field (let's call it _ReturnValue).  Define a ReturnValue property that returns the value in _ReturnValue.

     

    Often, your class will need methods to query the status of the thread such as: WaitForCompletion -- call _MyThread.Join.  IsStillRunning -- call _MyThread.IsAlive.

    Thursday, October 04, 2007 12:36 AM
  • You can use the ThreadPool.QueueUserWorkItem to asynchronously invoke code.  The WaitCallback delegate will be called with the given state, which can include a reference for the "result" of code. For example:

    Code Block

    class MyClass

    {

        private class State

        {

            public EventWaitHandle eventWaitHandle = new ManualResetEvent(false);

            public int result;

            public object parameters[];

        }

        private static void PerformUserWorkItem( Object stateObject )

        {

            State state = stateObject as State;

            if(state != null)

            {

                // do something lengthy with state.parameters...

                state.result = 42;

                state.eventWaitHandle.Set(); // signal we're done

            }

        }

        public static object DoWorkSynchronous()

        {

            State state = new State();

            ThreadPool.QueueUserWorkItem(PerformUserWorkItem, state);

            state.eventWaitHandle.WaitOne();

            Console.WriteLine(state.result);

            return state.result;

        }

    }

     

     

     

     

     

    Thursday, October 04, 2007 7:14 PM
    Moderator
  • You can get it ;) Here is the code:
     
            private static int DoSomething()
            {
                return 5;
            }

            static int x = 0;

           Thread thread= new Thread(delegate()
                {
                    x = DoSomething();
                });

            private void DoSomething_Click(object sender, EventArgs e)
            {
                if (!thread.IsAlive)
                {
                    thread= new Thread(delegate()
                    {
                        x = DoSomething();
                    });
                    thread.Start();

                    //Return is not instant. After thread dies it will return result.
                    while (thread.IsAlive)
                    {
                        Thread.Sleep(150);
                    }
                    tbResult.Text = x.ToString();
                }
            }

    • Proposed as answer by armin3 Saturday, July 04, 2009 8:13 AM
    Saturday, July 04, 2009 6:36 AM