views:

364

answers:

3

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?

+4  A: 

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.)

Jeff Sternal
A: 

Have a look at the Asynchronous Programming Model.

In one of the common patterns the model describes, your class will expose BeginXXX and EndXXX methods. The former starts the asynchronous operation and returns an IAsyncResult object. The latter accepts the IAsyncResult object as an argument, blocks the calling thread until the operation is complete and returns the required value.

AdamRalph
+2  A: 

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);

    }
}
Jacob Ewald
I sleep it because I need to watch for user cancels and signal the thread to stop.
Chu
Chu: What you're describing is a classic scenario for a BackgroundWorker component (if you're on Windows Forms). That's much better than sleeping the UI thread for a second at a time.
itowlson
+1 for BackgroundWorker. It has built-in methods for showing execution progress and cancelling the task, not to mention it won't lock the UI thread while it's executing. If the user hits a cancel button on your UI thread you can set the flag on the backgroundworker and then check the CancellationPending property to know when to jump out of your async task.
Jacob Ewald