Returning a value from thread? Returning a value from thread? multithreading multithreading

Returning a value from thread?


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}


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.


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 10Work Line: 1, tid 6Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Work Line: 2, tid 6Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Work Line: 3, tid 6Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Work Line: 4, tid 6Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Work Line: 5, tid 6Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Waiting in Main, tid 10Completed, 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.