2012-03-22 25 views
1

我的主窗体Form1运行了我的程序的主体。C#获取原始线程来设置文本框的值

我有一个单独的线程开始执行算法。

当我从运行新线程的方法,方法MyAlgorithm()我得到的错误

InvalidOperationException异常与消息,“控制控制的名字从比它创建的线程以外的线程访问。”

如何返回到原始线程以便我可以运行该方法以使用最新值更新我的文本框?

这是我想要运行的方法,包含在我的应用程序中的主要类Form1中。我已经看过Invoke()方法,但我不知道如何从线程方法获取我的Form1的原始实例。

我调用我的线程是这样的...

 // Set the algorithm method up in it's own thread 
     Thread thread = new Thread(new ThreadStart(MyAlgorithm)); 

     // Run the algorithm 
     thread.Start(); 
+0

[跨线程操作无效:从其创建的线程以外的线程访问控件]的可能重复(http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid -control-accessible-from-a-thread-other-the) – 2012-03-22 17:47:01

回答

2

Control.Invoke()看一看:

public void ShowResults() 
{ 
    while (true) 
    { 
    Thread.Sleep(1000); // don't spam the UI thread 

    if (this.InvokeRequired) 
    { 
     this.Invoke((Action)UpdateGui); 
    } 
    else 
    { 
     UpdateGui(); 
    } 
    } 
} 

private void UpdateGui() 
{ 
    loopsNum.Text = Convert.ToString(resultLoopsNum); 
    nodesVisitedNum.Text = Convert.ToString(resultNodesVisitedNum); 
    nodesResolvedNum.Text = Convert.ToString(resultNodesResolvedNum); 
    cpuLoopsNum.Text = Convert.ToString(resultCpuLoopsNum); 
    shortestPathCostNum.Text = Convert.ToString(resultShortestPathCost); 
} 
+0

感谢您的帮助,它现在正在工作。但我不太明白为什么它需要成为一个“Action”对象。 Invoke何时不需要Action对象而不仅仅是一个函数名? – Luke 2012-03-23 09:12:09

+1

这是因为此方法可用于调用任何方法,而不仅仅是具有给定签名的方法。看看[this overload](http://msdn.microsoft.com/en-us/library/a1hetckb.aspx)。 – Gene 2012-03-23 09:22:29

+0

此外,你会发现一个很好的解释[在这个问题](http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call)。 – Gene 2012-03-23 09:29:55

1

您可以使用:

myform.Invoke(ShowResults); 
5

如何回到原来的线程,这样我可以运行方法来更新我的文本框与最新值?

在Windows窗体,你要么使用Control.Invoke/BeginInvoke使用BackgroundWorker和进度事件处理程序进行更新。您可以使用Dispatcher.Invoke/BeginInvoke

在C#5和.NET 4.5,你就可以使用异步方法应该做了很多这方面简单得多......

我已经看过了的invoke()方法,但我不知道如何从线程方法中获取Form1的原始实例。

如果“螺纹法”只是一种对Form的实例方法,那么你已经得到了this参考。如果不是,那么您需要提供该信息 - 理想情况下为ISynchronizeInvoke以避免直接依赖Windows窗体,如果可以分别表示“更新”部分。 (现在这个界面已经被弃用了,但是它仍然适用于同步上下文。)

1

这里有太多的其他选择:

或者使用System.Forms.Timer以定期调用ShowResults。或者另一个选项是而不是使用另一个线程来执行操作;在GUI线程中执行此操作,并在要更新GUI时从操作中调用Application.DoEvents()

第一个选项很好,因为它可以防止意外淹没GUI和Invoke请求,第二个选项很好,因为它全部位于GUI线程上,并允许您在事物显示时进行细粒度控制GUI。