从Thread.Start()的委托函数访问返回值

时间:2009-12-21 19:58:31

标签: c# multithreading

我有一个程序通过Thread.Start执行一个方法。该方法具有我想要访问的返回值。有没有办法做到这一点?这是一个抽样......

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

t.Start();

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

// Check the value of someValue

因此,一旦while循环结束,someValue应该被设置 - 但是因为它在另一个线程中执行它不会被设置。是否有一种简单的方法可以访问它?

5 个答案:

答案 0 :(得分:6)

当调用者和线程方法共享变量时,您已经可以访问它 - 一旦线程完成,您只需检查someValue

当然,您必须知道线程方法何时完成才有用。在底部,有两种方法可以做到这一点:

  • 将回调发送到完成后可以执行的线程方法。您可以传递回调方法someValue。如果你不关心回调执行时,你可以使用这种技术。

  • 使用某种WaitHandle(或Thread.Join)。它们告诉您资源何时准备好或事件已完成。如果您想要启动一个线程,执行其他操作,然后等待线程完成后再继续操作,此技术非常有用。 (换句话说,如果你想直接与线程同步备份,那就很有用了。)

答案 1 :(得分:5)

我无法重新创建您的问题,我有相同的代码,我看到了预期的结果。如果你只是要打开当前线程直到它完成,你可以在线程上调用.Join()并等待确保它已经完成执行。

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

    }
}

答案 2 :(得分:2)

从Thread返回值的一种可能方法是使用上下文类作为参数对象。它也可用于传递参数并检索结果。

另一方面,如果您可以使用BackgroundWorker类,它已经有一个专用的Result对象 - 它的工作方式相同。但是BackgroundWorker不能用于某些目的(例如,它不支持STA Apartment State)。

请记住,在线程完成之前你不应该从ctx.Result读取(即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; }
    }

答案 3 :(得分:1)

您可以使用委托回调从Thread函数检索数据。委托可以充当线程和调用者之间的桥梁。例如:

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

答案 4 :(得分:0)

查看Asynchronous Programming Model

在模型描述的一种常见模式中,您的类将公开BeginXXX和EndXXX方法。前者启动异步操作并返回IAsyncResult对象。后者接受IAsyncResult对象作为参数,阻塞调用线程直到操作完成并返回所需的值。