2014-09-11 48 views
0

例如,我的Windows窗體上有兩個Command按鈕和一個文本框。
在單擊該命令按鈕1,文本框的值不斷遞增說從1到1000000代碼運行時Windows窗體無法訪問

雖然出現這種情況,我不能夠在任何地方點擊的形式,包括命令按鈕2.
我可以再次訪問形式,只有當櫃檯1000000

請諮詢站於此。

我也使用modelless形式使用*.Show();方法嘗試。

這是我的代碼來獲取文本框中的值。

for (int i = 0; i <= 10000; i++) 
{ 
    Console.WriteLine(i); 
    this.textBox1.Text = Convert.ToString(i); 

    label2.Focus(); 
    this.textBox1.Focus(); 
} 
+5

這是因爲您正在UI上運行所有代碼,然後無法處理顯示更新。 – 2014-09-11 11:38:09

+1

應用程序只有在抽取消息時纔會響應。如果您的應用程序在代碼中間的循環中忙於旋轉,則無法泵送消息,除非您告訴它(但不要!) – 2014-09-11 11:40:59

+0

如果您的代碼在UI線程中運行,那麼它將阻塞,直到您代碼已經完成運行。看一下'Task'類在一個單獨的線程中執行它。 http://msdn.microsoft.com/en-us/library/system.threading.tasks.task(v=vs.110).aspx – 2014-09-11 11:43:00

回答

0

原因是你正在做一個需要一段時間才能完成的任務,在你想要發生事件的同一個線程中(即點擊按鈕)。在單個線程中,所有任務都以一系列方式完成(一次一個)。換句話說,如果一個任務完成,那麼另一個任務將開始。

要做到這一點,你需要在另一個線程(而不是在主線程)運行此任務。我希望這個DotNet Perls Link 可以幫助你。

0

爲了與來自不同線程的UI進行交互,您需要使用委託「調用」UI線程的調用,並調用Control.Invoke/BeginInvoke

例如,你可以使用:

textBox1.Invoke((MethodInvoker)(() => textBox1.Text = Convert.ToString(i))); 

所有括號的方式獲得了一點,所以你可能要添加一個擴展方法就是這樣,如果你使用C#3.0:

public static void Invoke(this Control control, MethodInvoker action) 
{ 
    control.Invoke(action); 
} 

然後,你可以這樣做:

textBox1.Invoke(() => textBox1.Text = Convert.ToString(i)); 
0

一個Windows的主( 「用戶界面」)螺紋形式應用程ation基本上是一個處理隊列中消息的無限循環。當用戶移動或點擊鼠標,按下按鍵等時,操作系統將確定哪個應用程序應該處理該輸入並將消息添加到相應應用程序的隊列中。當通知其消息隊列包含消息時,應用程序將處理消息。例如,如果Windows窗體控件收到點擊,它會觸發由用戶代碼處理的Click事件。

這是你的代碼進來。在你的榜樣,你寫的是經歷了漫長的循環更新UI運行的第一個命令按鈕單擊處理程序。在您的代碼正在運行時,不會處理隊列中的其他消息。這意味着其他控件(如命令按鈕2)的點擊沒有被處理。只有在您的Click處理程序返回後,消息循環纔會繼續處理事件。

爲了保持UI響應,你可以使用一個System.Windows.Forms.Timer設置爲一個較短的時間間隔做一個迭代的工作在你的循環處理它的方法蜱。這樣你只需要爲每個時鐘週期簡單地綁定UI線程,並且其他事件可以在滴答之間處理。

或者,您可以瞭解如何在後臺線程上工作,但由於單擊處理程序中的大部分工作正在更新UI,因此這可能不是最佳解決方案。從後臺線程更新UI是不合法的;正如Kai所討論的那樣,更新UI的方法必須使用Control.InvokeControl.BeginInvoke在UI線程上運行。