Returning a value from thread?

C#.NetMultithreading

C# Problem Overview


How do I return a value from a thread?

C# Solutions


Solution 1 - C#

One of the easiest ways to get a return value from a thread is to use closures. Create a variable that will hold the return value from the thread and then capture it in a lambda expression. Assign the "return" value to this variable from the worker thread and then once that thread ends you can use it from the parent thread.

void Main()
{
  object value = null; // Used to store the return value
  var thread = new Thread(
    () =>
    {
      value = "Hello World"; // Publish the return value
    });
  thread.Start();
  thread.Join();
  Console.WriteLine(value); // Use the return value here
}

Solution 2 - C#

It depends on how do you want to create the thread and available .NET version:

.NET 2.0+:

A) You can create the Thread object directly. In this case you could use "closure" - declare variable and capture it using lambda-expression:

object result = null;
Thread thread = new System.Threading.Thread(() => { 
    //Some work...
    result = 42; });
thread.Start();
thread.Join();
Console.WriteLine(result);

B) You can use delegates and IAsyncResult and return value from EndInvoke() method:

delegate object MyFunc();
...
MyFunc x = new MyFunc(() => { 
    //Some work...
    return 42; });
IAsyncResult asyncResult = x.BeginInvoke(null, null);
object result = x.EndInvoke(asyncResult);

C) You can use BackgroundWorker class. In this case you could use captured variable (like with Thread object) or handle RunWorkerCompleted event:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
    //Some work...
    e.Result = 42;
};
worker.RunWorkerCompleted += (s, e) => {
    //e.Result "returned" from thread
    Console.WriteLine(e.Result);
};
worker.RunWorkerAsync();

.NET 4.0+:

Starting with .NET 4.0 you could use Task Parallel Library and Task class to start your threads. Generic class Task<TResult> allows you to get return value from Result property:

//Main thread will be blocked until task thread finishes
//(because of obtaining the value of the Result property)
int result = Task.Factory.StartNew(() => {
    //Some work...
    return 42;}).Result;

.NET 4.5+:

Starting with .NET 4.5 you could also use async/await keywords to return value from task directly instead of obtaining Result property:

int result = await Task.Run(() => {
    //Some work...
    return 42; });

Note: method, which contains the code above shoud be marked with asynckeyword.

For many reasons using of Task Parallel Library is preferable way of working with threads.

Solution 3 - C#

I would use the BackgroundWorker approach and return the result in e.Result.

EDIT:

This is commonly associated with WinForms and WPF, but can be used by any type of .NET application. Here's sample code for a console app that uses BackgroundWorker:

using System;
using System.Threading;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;

namespace BGWorker
{
    class Program
    {
        static bool done = false;

        static void Main(string[] args)
        {
            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            bg.RunWorkerAsync();

            while (!done)
            {
                Console.WriteLine("Waiting in Main, tid " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(100);
            }
        }

        static void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("Completed, tid " + Thread.CurrentThread.ManagedThreadId);
            done = true;
        }

        static void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine("Work Line: " + i + ", tid " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(500);
            }
        }
    }
}

Output:

Waiting in Main, tid 10
Work Line: 1, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 2, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 3, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 4, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 5, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Completed, tid 6

2014 UPDATE

See @Roger's answer below.

https://stackoverflow.com/a/24916747/141172

He points out that you can use a Task that returns a Task<T>, and check Task<T>.Result.

Solution 4 - C#

A thread isn't a method - you don't normally "return" a value.

However, if you're trying to fetch a value back from the results of some processing, you have many options, the two main ones being:

  • You can synchronize a shared piece of data, and set it appropriately.
  • You can also pass the data back in some form of callback.

It really depends on how you're creating the thread, and how you want to use it, as well as the language/framework/tools you're using.

Solution 5 - C#

Simply use the delegate approach.

int val;
Thread thread = new Thread(() => { val = Multiply(1, 2); });
thread.Start();

Now make Multiply function that will work on another thread:

int Multiply(int x, int y)
{
    return x * y;
}

Solution 6 - C#

My favorite class, runs any method on another thread with just 2 lines of code.

class ThreadedExecuter<T> where T : class
{
    public delegate void CallBackDelegate(T returnValue);
    public delegate T MethodDelegate();
    private CallBackDelegate callback;
    private MethodDelegate method;

    private Thread t;

    public ThreadedExecuter(MethodDelegate method, CallBackDelegate callback)
    {
        this.method = method;
        this.callback = callback;
        t = new Thread(this.Process);
    }
    public void Start()
    {
        t.Start();
    }
    public void Abort()
    {
        t.Abort();
        callback(null); //can be left out depending on your needs
    }
    private void Process()
    {
        T stuffReturned = method();
        callback(stuffReturned);
    }
}

usage

    void startthework()
    {
        ThreadedExecuter<string> executer = new ThreadedExecuter<string>(someLongFunction, longFunctionComplete);
        executer.Start();
    }
    string someLongFunction()
    {
        while(!workComplete)
            WorkWork();
        return resultOfWork;
    }
    void longFunctionComplete(string s)
    {
        PrintWorkComplete(s);
    }

Beware that longFunctionComplete will NOT execute on the same thread as starthework.

For methods that take parameters you can always use closures, or expand the class.

Solution 7 - C#

Here is a simple example using a delegate ...

void Main()
{
   DoIt d1 = Doer.DoThatThang;
   DoIt d2 = Doer.DoThatThang;
   
   IAsyncResult r1 = d1.BeginInvoke( 5, null, null );
   IAsyncResult r2 = d2.BeginInvoke( 10, null, null );
   
   Thread.Sleep( 1000 );
   
   var s1 = d1.EndInvoke( r1 );
   var s2 = d2.EndInvoke( r2 );
   
   s1.Dump(); // You told me 5
   s2.Dump(); // You told me 10
}

public delegate string DoIt( int x );

public class Doer
{
  public static string DoThatThang( int x  )
  {
    return "You told me " + x.ToString();
  }
}

There's a terrific series on threading at Threading in C#.

Solution 8 - C#

With the latest .NET Framework, it is possible to return a value from a separate thread using a Task, where the Result property blocks the calling thread until the task finishes:

  Task<MyClass> task = Task<MyClass>.Factory.StartNew(() =>
  {
      string s = "my message";
      double d = 3.14159;
      return new MyClass { Name = s, Number = d };
  });
  MyClass test = task.Result;

For details, please see http://msdn.microsoft.com/en-us/library/dd537613(v=vs.110).aspx

Solution 9 - C#

I came across this thread when also trying to obtain the return value of a method that gets executed within a Thread. I thought I would post my solution that works.

This solution uses an class to store both the method to be executed (indirectly) and stores the returning value. The class can be used for any function and any return type. You just instantiate the object using the return value type and then pass the function to call via a lambda (or delegate).


C# 3.0 Implementation


public class ThreadedMethod<T>
{

	private T mResult;
	public T Result 
	{
		get { return mResult; }
		private set { mResult = value; }
	}

	public ThreadedMethod()
	{
	}

	//If supporting .net 3.5
	public void ExecuteMethod(Func<T> func)
	{
		Result = func.Invoke();
	}

	//If supporting only 2.0 use this and 
	//comment out the other overload
	public void ExecuteMethod(Delegate d)
	{
		Result = (T)d.DynamicInvoke();
	}
}

To use this code you can use a Lambda (or a delegate). Here is the example using lambdas:

ThreadedMethod<bool> threadedMethod = new ThreadedMethod<bool>();
Thread workerThread = new Thread((unused) => 
							threadedMethod.ExecuteMethod(() => 
								SomeMethod()));
workerThread.Start();
workerThread.Join();
if (threadedMethod.Result == false) 
{
	//do something about it...
}

VB.NET 2008 Implementation


Anyone using VB.NET 2008 can't use lambdas with non-value returning methods. This affects the ThreadedMethod class, so we'll make ExecuteMethod return the value of the function. This doesn't hurt anything.

Public Class ThreadedMethod(Of T)

	Private mResult As T
	Public Property Result() As T
		Get
			Return mResult
		End Get
		Private Set(ByVal value As T)
			mResult = value
		End Set
	End Property

	Sub New()
	End Sub

	'If supporting .net 3.5'
	Function ExecuteMethod(ByVal func As Func(Of T)) As T
	    Result = func.Invoke()
	    Return Result
	End Function

	'If supporting only 2.0 use this and' 
	'comment out the other overload'
	Function ExecuteMethod(ByVal d As [Delegate]) As T
		Result = DirectCast(d.DynamicInvoke(), T)
		Return Result
	End Function

End Class

Solution 10 - C#

ThreadStart delegates in C# used to start threads have return type 'void'.

If you wish to get a 'return value' from a thread, you should write to a shared location (in an appropriate thread-safe manner) and read from that when the thread has completed executing.

Solution 11 - C#

If you don't want to use a BackgroundWorker, and just use a regular Thread, then you can fire an event to return data like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadWithDataReturnExample
{
    public partial class Form1 : Form
    {
        private Thread thread1 = null;
        
        public Form1()
        {
            InitializeComponent();

            thread1 = new Thread(new ThreadStart(this.threadEntryPoint));
            Thread1Completed += new AsyncCompletedEventHandler(thread1_Thread1Completed);
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            thread1.Start();
            //Alternatively, you could pass some object
            //in such as Start(someObject);
            //With apprioriate locking, or protocol where
            //no other threads access the object until
            //an event signals when the thread is complete,
            //any other class with a reference to the object 
            //would be able to access that data.
            //But instead, I'm going to use AsyncCompletedEventArgs 
            //in an event that signals completion
        }
               
        void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
        {
            if (this.InvokeRequired)
            {//marshal the call if we are not on the GUI thread                
                BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
                  new object[] { sender, e });
            }
            else
            {
                //display error if error occurred
                //if no error occurred, process data
                if (e.Error == null)
                {//then success
                   
                    MessageBox.Show("Worker thread completed successfully");
                    DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
                    MessageBox.Show("Your data my lord: " + someData.someProperty);

                }
                else//error
                {
                    MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
                }
            }
        }

        #region I would actually move all of this into it's own class
            private void threadEntryPoint()
            {
                //do a bunch of stuff

                //when you are done:
                //initialize object with data that you want to return
                DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();
                dataYouWantToReturn.someProperty = "more data";

                //signal completion by firing an event
                OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
            }

            /// <summary>
            /// Occurs when processing has finished or an error occurred.
            /// </summary>
            public event AsyncCompletedEventHandler Thread1Completed;
            protected virtual void OnThread1Completed(AsyncCompletedEventArgs e)
            {
                //copy locally
                AsyncCompletedEventHandler handler = Thread1Completed;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
        #endregion

    }
}

Solution 12 - C#

Can use This Code:

 private Object MyThread(Object Data)
      {
        Object response = null;
        Thread newThread = new Thread(() =>
        {
            response = MyFunction(Data);
            //MyFunction Is Function that you Define
        });
        newThread.Start();
        newThread.Join();
        return response;
      }

Solution 13 - C#

Threads do not really have return values. However, if you create a delegate, you can invoke it asynchronously via the BeginInvoke method. This will execute the method on a thread pool thread. You can get any return value from such as call via EndInvoke.

Example:

static int GetAnswer() {
   return 42;
}

...

Func<int> method = GetAnswer;
var res = method.BeginInvoke(null, null); // provide args as needed
var answer = method.EndInvoke(res);

GetAnswer will execute on a thread pool thread and when completed you can retrieve the answer via EndInvoke as shown.

Solution 14 - C#

The BackgroundWorker is nice when developing for Windows Forms.

Say you wanted to pass a simple class back and forth:

class Anything {
	// Number and Text are for instructional purposes only
	public int Number { get; set; }
	public string Text { get; set; }
	// Data can be any object - even another class
	public object Data { get; set; }
}

I wrote up a short class that does the following:

  • Create or Clear a list
  • Start a loop
  • In loop, create a new item for the list
  • In loop, create a thread
  • In loop, send the item as a parameter to the thread
  • In loop, start the thread
  • In loop, add thread to list to watch
  • After loop, join each thread
  • After all joins have completed, display the results

From inside the thread routine:

  • Call lock so that only 1 thread can enter this routine at a time (others have to wait)
  • Post information about the item.
  • Modify the item.
  • When the thread completes, the data is displayed on the console.

Adding a delegate can be useful for posting your data directly back to your main thread, but you may need to use Invoke if some of the data items are not thread safe.

class AnyTask {

	private object m_lock;

	public AnyTask() {
		m_lock = new object();
	}
	// Something to use the delegate
	public event MainDelegate OnUpdate;

	public void Test_Function(int count) {
		var list = new List<Thread>(count);
		for (var i = 0; i < count; i++) {
			var thread = new Thread(new ParameterizedThreadStart(Thread_Task));
			var item = new Anything() {
				Number = i,
				Text = String.Format("Test_Function #{0}", i)
			};
			thread.Start(item);
			list.Add(thread);
		}
		foreach (var thread in list) {
			thread.Join();
		}
	}

	private void MainUpdate(Anything item, bool original) {
		if (OnUpdate != null) {
			OnUpdate(item, original);
		}
	}

	private void Thread_Task(object parameter) {
		lock (m_lock) {
			var item = (Anything)parameter;
			MainUpdate(item, true);
			item.Text = String.Format("{0}; Thread_Task #{1}", item.Text, item.Number);
			item.Number = 0;
			MainUpdate(item, false);
		}
	}

}

To test this, create a little Console Application, and put this in the Program.cs file:

// A delegate makes life simpler
delegate void MainDelegate(Anything sender, bool original);

class Program {

	private const int COUNT = 15;
	private static List<Anything> m_list;

	static void Main(string[] args) {
		m_list = new List<Anything>(COUNT);
		var obj = new AnyTask();
		obj.OnUpdate += new MainDelegate(ThreadMessages);
		obj.Test_Function(COUNT);
		Console.WriteLine();
		foreach (var item in m_list) {
			Console.WriteLine("[Complete]:" + item.Text);
		}
		Console.WriteLine("Press any key to exit.");
		Console.ReadKey();
	}

	private static void ThreadMessages(Anything item, bool original) {
		if (original) {
			Console.WriteLine("[main method]:" + item.Text);
		} else {
			m_list.Add(item);
		}
	}

}

Here is a screenshot of what I got with this:

Console Output

I hope others can understand what I've tried to explain.

I enjoy working on threads and using delegates. They make C# a lot of fun.

Appendix: For VB Coders

I wanted to see what was involved in writing the code above as a VB Console Application. The conversion involved a few things I didn't expect, so I will update this thread here for those wanting to know how to thread in VB.

Imports System.Threading

Delegate Sub MainDelegate(sender As Anything, original As Boolean)

Class Main

	Private Const COUNT As Integer = 15
	Private Shared m_list As List(Of Anything)

	Public Shared Sub Main(args As String())
		m_list = New List(Of Anything)(COUNT)
		Dim obj As New AnyTask()
		AddHandler obj.OnUpdate, New MainDelegate(AddressOf ThreadMessages)
		obj.Test_Function(COUNT)
		Console.WriteLine()
		For Each item As Anything In m_list
			Console.WriteLine("[Complete]:" + item.Text)
		Next
		Console.WriteLine("Press any key to exit.")
		Console.ReadKey()
	End Sub

	Private Shared Sub ThreadMessages(item As Anything, original As Boolean)
		If original Then
			Console.WriteLine("[main method]:" + item.Text)
		Else
			m_list.Add(item)
		End If
	End Sub

End Class

Class AnyTask

	Private m_lock As Object

	Public Sub New()
		m_lock = New Object()
	End Sub
	' Something to use the delegate
	Public Event OnUpdate As MainDelegate

	Public Sub Test_Function(count As Integer)
		Dim list As New List(Of Thread)(count)
		For i As Int32 = 0 To count - 1
			Dim thread As New Thread(New ParameterizedThreadStart(AddressOf Thread_Task))
			Dim item As New Anything()
			item.Number = i
			item.Text = String.Format("Test_Function #{0}", i)
			thread.Start(item)
			list.Add(thread)
		Next
		For Each thread As Thread In list
			thread.Join()
		Next
	End Sub

	Private Sub MainUpdate(item As Anything, original As Boolean)
		RaiseEvent OnUpdate(item, original)
	End Sub

	Private Sub Thread_Task(parameter As Object)
		SyncLock m_lock
			Dim item As Anything = DirectCast(parameter, Anything)
			MainUpdate(item, True)
			item.Text = [String].Format("{0}; Thread_Task #{1}", item.Text, item.Number)
			item.Number = 0
			MainUpdate(item, False)
		End SyncLock
	End Sub

End Class


Class Anything
	' Number and Text are for instructional purposes only
	Public Property Number() As Integer
		Get
			Return m_Number
		End Get
		Set(value As Integer)
			m_Number = value
		End Set
	End Property
	Private m_Number As Integer
	Public Property Text() As String
		Get
			Return m_Text
		End Get
		Set(value As String)
			m_Text = value
		End Set
	End Property
	Private m_Text As String
	' Data can be anything or another class
	Public Property Data() As Object
		Get
			Return m_Data
		End Get
		Set(value As Object)
			m_Data = value
		End Set
	End Property
	Private m_Data As Object
End Class

Solution 15 - C#

class Program
{
    static void Main(string[] args)
    {
        string returnValue = null;
       new Thread(
          () =>
          {
              returnValue =test() ; 
          }).Start();
        Console.WriteLine(returnValue);
        Console.ReadKey();
    }

    public static string test()
    {
        return "Returning From Thread called method";
    }
}

Solution 16 - C#

A simple solution is to pass a parameter by ref to the function that is running in the thread and change its value in the thread.

       // create a list of threads
        List<Thread> threads = new List<Thread>();


        //declare the ref params
        bool is1 = false;
        bool is2 = false;

        threads.Add(new Thread(() => myFunction(someVar, ref is1)));
        threads.Add(new Thread(() => myFunction(someVar, ref is2)));

        threads.ForEach(x => x.Start());

        // wait for threads to finish
        threads.ForEach(x => x.Join());
       
        //check the ref params
        if (!is1)
        {
          //do something
        }

        if (!is2)
        {
           //do somethign else
        }

If you can't change the function that is running in the tread, you can wrap it another function:

 bool theirFunction(var someVar){
   return false;
}


 void myFunction(var someVar ref bool result){
  result = theirFunction(myVar);
 }

Solution 17 - C#

class Program
{
    public static void ActionResultPrint(string i)
    {
        Console.WriteLine(i);
    }

    static void Main(string[] args)
    {
        var tl = new List<Thread>();

        tl.Add(new Thread(() => Run(10, ActionResultPrint)));
        tl.Add(new Thread(() => Run(20, ActionResultPrint)));
        tl.ForEach(x => x.Start());
        tl.ForEach(x => x.Join());
    }

    public static void Run(int j, Action<string> action)
    {
        string rvalue = string.Empty;

        for (int i = 0; i <= j; i++)
        {
            Thread.Sleep(100);
            rvalue = i.ToString();
            Console.WriteLine(rvalue);
        }
        action($@"output {j}");
    }
}

Solution 18 - C#

when threads are used , value can be passed and returned in following ways:

int value = -1;
  Thread t1 = new Thread(() => { value = compute(a); });
   t1.Start();
 if(value!=-1)
 {...}

   public int compute(int[] a1)
    {
	//...code logic
        return -1;
    }

Solution 19 - C#

I'm no kind of expert in threading, that's why I did it like this:

I created a Settings file and

Inside the new thread:

Setting.Default.ValueToBeSaved;
Setting.Default.Save();

Then I pick up that value whenever I need it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAsadView Question on Stackoverflow
Solution 1 - C#Brian GideonView Answer on Stackoverflow
Solution 2 - C#Igor BendrupView Answer on Stackoverflow
Solution 3 - C#Eric J.View Answer on Stackoverflow
Solution 4 - C#Reed CopseyView Answer on Stackoverflow
Solution 5 - C#yogihostingView Answer on Stackoverflow
Solution 6 - C#ErikView Answer on Stackoverflow
Solution 7 - C#JP AliotoView Answer on Stackoverflow
Solution 8 - C#user8128167View Answer on Stackoverflow
Solution 9 - C#MattView Answer on Stackoverflow
Solution 10 - C#jscharfView Answer on Stackoverflow
Solution 11 - C#AaronLSView Answer on Stackoverflow
Solution 12 - C#Ali asghar FendereskiView Answer on Stackoverflow
Solution 13 - C#Brian RasmussenView Answer on Stackoverflow
Solution 14 - C#jp2codeView Answer on Stackoverflow
Solution 15 - C#Shyam sundar shahView Answer on Stackoverflow
Solution 16 - C#CodeToadView Answer on Stackoverflow
Solution 17 - C#김민석View Answer on Stackoverflow
Solution 18 - C#PrashSEView Answer on Stackoverflow
Solution 19 - C#PatrikView Answer on Stackoverflow