2009-12-21 28 views
5

我有一个通过Thread.Start执行方法的程序。该方法有一个我想访问的返回值。有没有办法做到这一点?这里有一个采样...从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中应设置 - 而是因为它在另一个线程中执行它不会设置。有一种简单的方法可以访问它吗?

+2

您是否尝试过将''volatile'声明为someValue? – 2009-12-21 20:00:28

+0

尽管这种同步技术很奇怪,但它应该与volatile修饰符一起使用。 +1为匿名 – 2009-12-21 20:07:00

回答

5

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

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

  • 发送回调到线程方法,它可以在完成时执行。您可以传递回调方法someValue。如果您不在乎执行回调的时间,可以使用这种技术。

  • 使用某种WaitHandle(或Thread.Join)。这些告诉你什么时候资源已经准备好或者事件已经完成。如果您想要启动线程,执行其他操作,则此技术非常有用,然后然后等待线程完成后再继续。 (换句话说,它如果要同步备份与线程是非常有用的,只是不是现在。)

0

看一看的Asynchronous Programming Model

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

4

我不能重新创建你的问题,我有相同的代码,我看到了预期的结果。如果你只是想要休眠当前线程直到它完成,你可以在线程中调用.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); 

    } 
} 
+0

我睡觉了,因为我需要注意用户取消并指示线程停止。 – bugfixr 2009-12-21 20:38:30

+4

Chu:您所描述的是BackgroundWorker组件(如果您使用的是Windows窗体)的经典场景。这比每次睡一次UI线程要好得多。 – itowlson 2009-12-21 20:41:21

+0

+1为BackgroundWorker。它具有显示执行进度和取消任务的内置方法,更不用说在执行时不会锁定UI线程。如果用户在UI线程上点击取消按钮,则可以在背景工作器上设置标志,然后检查CancellationPending属性以知道何时跳出异步任务。 – 2009-12-21 20:56:38

1

从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; } 
    } 
0

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

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