代码之家  ›  专栏  ›  技术社区  ›  bugfixr

从thread.start()的委托函数访问返回值

  •  6
  • bugfixr  · 技术社区  · 16 年前

    我有一个通过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 回复  |  直到 9 年前
        1
  •  6
  •   Jeff Sternal    16 年前

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

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

    • 将回调发送到线程方法中,该方法可以在完成后执行。您可以传递回调方法 索马里 . 如果不关心回调何时执行,则可以使用此技术。

    • 使用A WaitHandle 某种类型的(或 Thread.Join )这些信息告诉您资源何时准备好或事件何时完成。如果你想启动一个线程,做些别的事情,这种技术是很有用的。 然后 等待线程完成后再继续。(换句话说,如果您想与线程同步备份,这是很有用的,而不是马上同步。)

        2
  •  5
  •   Jacob Ewald    16 年前

    我无法重新创建您的问题,我有相同的代码,并且看到了预期的结果。如果您只想睡眠当前线程直到它完成,那么您可以在该线程上调用.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);
    
        }
    }
    
        3
  •  2
  •   andrew.fox    11 年前

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

    另一方面,如果您可以使用BackgroundWorker类,那么它已经有了一个专用的result对象——其工作方式相同。但BackgroundWorker不能用于某些目的(例如,它不支持STA公寓状态)。

    记住,在线程完成之前,不应该从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; }
        }
    
        4
  •  1
  •   Jackypengyu    9 年前

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

    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);
        }
    }
    
        5
  •  0
  •   Adam Ralph    16 年前

    看看 Asynchronous Programming Model .

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