2012-03-22 22 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。