Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access return value from Thread.Start()'s delegate function

I've got a program that executes a method through a Thread.Start. The method has a return value that I'd like to get access to. Is there a way to do this? Here's a sampling...

var someValue = "";
Thread t = new Thread(delegate() { someValue = someObj.methodCall(); });

t.Start();

while (t.isAlive) Thread.Sleep(1000);

// Check the value of someValue

So once the while loop ends, the someValue should be set - but because it's executed in another thread it doesn't get set. Is there a simple way to get access to it?

like image 316
bugfixr Avatar asked Dec 21 '09 19:12

bugfixr


People also ask

How do you return a value from a delegate?

The key here is using the += operator (not the = operator) and looping through the list that is retrieved by calling GetInvocationList() and then calling Invoke() on each delegate retrieved. Hope this helps!

How to return value from thread in 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.

How do you return a value from a thread?

There are two main ways to return values from a thread, they are: Extend threading. Thread and store data in instance variables. Store data in global variables.

How do you return a value from thread run method in Java?

Solution : Create a Handler in UI Thread,which is called as responseHandler. Initialize this Handler from Looper of UI Thread. In HandlerThread , post message on this responseHandler.


4 Answers

When the caller and the threaded method share a variable, you already have access to it - once the thread has completed, you just check someValue.

Of course, you have to know when the threaded method is complete for this to be useful. At the bottom, there are two ways to do this:

  • Send a callback into the threaded method that it can execute when it's finished. You can pass your callback method someValue. You can use this technique if you don't care when the callback executes.

  • Use a WaitHandle of some kind (or Thread.Join). These tell you when a resource is ready or an event has completed. This technique is useful if you want to start a thread, do something else, then wait until the thread completes before proceeding. (In other words, it's useful if you want to sync back up with the thread, just not right away.)

like image 54
Jeff Sternal Avatar answered Oct 06 '22 11:10

Jeff Sternal


I can't recreate your issue, I've got the same code and I'm seeing the expected result. If you're just going to sleep the current thread until it's complete you could just call .Join() on the thread and wait to be sure it's done executing.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    string someValue = "";

    private void Form1_Load(object sender, EventArgs e)
    {

        Thread t = new Thread(delegate() { someValue = "asdf"; });

        t.Start();
        t.Join();

        //while (t.IsAlive) Thread.Sleep(1000);

        System.Diagnostics.Debug.Print(someValue);

    }
}
like image 37
Jacob Ewald Avatar answered Oct 06 '22 10:10

Jacob Ewald


One of possible methods to return a value from a Thread is to use a context class as a parameter object. It can be used to pass parameters and retrieve the result as well.

If on the other hand you could use a BackgroundWorker class, it has already a dedicated Result object - that works the same way. But BackgroundWorker cannot be used for some purposes (for instance, it doesn't support STA Apartment State).

Keep in mind that you shouldn't read from ctx.Result until the thread is finished (i.e. t.IsAlive == false).

    void runThread()        
    {
        ThreadContext ctx = new ThreadContext();
        ctx.Value = 8;

        Thread t = new Thread(new ParameterizedThreadStart(MyThread));
        //t.SetApartmentState(ApartmentState.STA); // required for some purposes
        t.Start(ctx);

        // ...
        t.Join();

        Console.WriteLine(ctx.Result);
    }

    private static void MyThread(object threadParam)
    {
        ThreadContext context = (ThreadContext)threadParam;

        context.Result = context.Value * 4; // compute result
    }

    class ThreadContext
    {
        public int Value { get; set; }
        public int Result { get; set; }
    }
like image 40
andrew.fox Avatar answered Oct 06 '22 09:10

andrew.fox


You can retrieve data from Thread function using delegate callback. The delegate can serve as a bridge between thread and the caller. For example:

public delegate void DelReturnValue(string value);
public class SayHello
{
    private string _name;
    private DelReturnValue _delReturnValue;

    public SayHello(string name, DelReturnValue delReturnValue)
    {
        _name = name;
        _delReturnValue = delReturnValue;
    }

    public void SayHelloMethod()
    {
        _delReturnValue(_name);
    }
}

public class Caller
{
    private static string _returnedValue;
    public static void ReturnValue(string value)
    {
        _returnedValue = value;
    }

    public static void Main()
    {
        DelReturnValue delReturnValue=new DelReturnValue(ReturnValue);
        SayHello sayHello = new SayHello("test", delReturnValue);
        Thread newThread = new Thread(new ThreadStart(sayHello.SayHelloMethod));
        newThread.Start();
        Thread.Sleep(1000);
        Console.WriteLine("value is returned: " + _returnedValue);
    }
}
like image 44
Jackypengyu Avatar answered Oct 06 '22 09:10

Jackypengyu