2013-05-09 168 views
0

此代碼在控制檯應用程序中正常工作,但是當我在Windows窗體應用程序中使用它時,它無法正常工作。它永不停止,也不會產生任何輸出。爲什麼while()循環在button_Click()方法的主體中不起作用

我用它在一個控制檯aplication這樣,它的工作原理:

static void Main(string[] args) 
    { 
    Console.WriteLine("Enter your boolean query"); 
     do{ 
      string query = Console.ReadLine(); 
      List<int> lst = ProcessQuery(query); 
      count = 0; 
      if (lst!=null) 
      { 
       foreach (int a in lst) 
       { 
        if (a == 1) 
        { 
         Console.WriteLine(documentContentList[count]); 
        } 
        count++; 
       } 
      } 
      else 
      { 
       Console.WriteLine("No search result found"); 
      } 

     } while(1==1); 

    } 

我嘗試在Windows窗體應用程序使用上面的代碼在button_click方法,但它不能正常工作。我認爲while(1==1)有什麼不對 - 是否有任何等價物?

這裏是我寫的按鈕的方法:

private void button6_Click(object sender, EventArgs e) 
    { 
     if (t == null) 
     { 
      MessageBox.Show("Click on LoadFile Button,Please."); 
      return; 
     } 
     if (textBox4.Text == "") 
     { 
      MessageBox.Show("Enter your Boolean Query"); 
      return; 
     } 
     listBox1.Items.Clear(); 
     DateTime dt = DateTime.Now; 
     do{ 
      List<int> lst = t.ProcessQuery(textBox4.Text); 
      count = 0; 
      if (lst != null) 
      { 
       foreach (int a in lst) 
       { 
        listBox1.Items.Add(t.documentContentList[count]); 
       } 
       count++; 
      } 
      else 
      { 
       listBox1.Items.Add("No Search Result Found"); 
      } 
      label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s"; 
     } while (1==1); 

    } 
+0

'while(1 == 1)'?????你打算做什麼?當你想擺脫while循環? – Arran 2013-05-09 14:37:17

+0

這是一個無限循環! – Obama 2013-05-09 14:37:40

+0

@Arren,是的,這是循環的一個斷點,但它不適用於Windows窗體應用程序,任何替換? – Olivia 2013-05-09 14:40:54

回答

3

我相信從button_click事件處理程序中刪除do while循環將爲您完成這項工作。

private void button6_Click(object sender, EventArgs e) 
    { 
     if (t == null) 
     { 
      MessageBox.Show("Click on LoadFile Button,Please."); 
      return; 
     } 
     if (textBox4.Text == "") 
     { 
      MessageBox.Show("Enter your Boolean Query"); 
      return; 
     } 
     listBox1.Items.Clear(); 
     DateTime dt = DateTime.Now; 
     //do{ 
      List<int> lst = t.ProcessQuery(textBox4.Text); 
      count = 0; 
      if (lst != null) 
      { 
       foreach (int a in lst) 
       { 
        listBox1.Items.Add(t.documentContentList[count]); 
       } 
       count++; 
      } 
      else 
      { 
       listBox1.Items.Add("No Search Result Found"); 
      } 
      label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s"; 
     // } while (1==1); 

    } 

控制檯應用程序暫停執行時,它會等待同步得到與

string query = Console.ReadLine(); 

用戶輸入時,它得到的輸入它所需的計算和打印無論是打印,並在等待下一個輸入再次是同一行。

一個WinForm應用程序不會以這種方式工作,它已經有一個事件循環處理UI活動(的keyPressed等)

總之,你並不需要在處理程序方法的循環。

+0

然後,您需要查看您的'ProcessQuery'方法的實現。它每次都返回'null'。 – JosephHirn 2013-05-09 16:04:17

+0

@tafa你說得對,謝謝。 – Olivia 2013-05-15 07:39:27

0

在Windows窗體或WPF中,UI僅由單個線程管理。因此,如果您的UI在其線程中調用的代碼中存在無限循環,它將永遠阻塞,並且無法繼續更新UI。這就是爲什麼你不會看到任何對話框出現。

相反,您應該在其自己的線程中運行類似此代碼的內容,或者可能更容易在BackgroundWorker對象的構造內運行(然後使用DoWork和ProgressChanged事件)。

0

在您的控制檯示例中,Consol.ReadLine()調用阻止UI &等待輸入。通過使用無限循環,您可以有效地允許用戶輸入儘可能多的查詢。然而,在一個基於Forms/WPF的應用程序中,一個無限循環實際上是一個糟糕的主意,再加上應用程序會一直保持到關閉狀態,而不是在完成工作時立即關閉(這就是爲什麼您在Console應用程序中使用無限循環的原因) 。

這是因爲基於表單的應用程序利用專用線程來更新UI。通過阻止此線程,您還可以防止任何其他UI更新發生,從而凍結您的應用程序。根據您要做的事情,button6_Click事件方法應該將這項工作分流到BackgroundWorker(documentation),該工作允許在另一個線程上執行工作,然後將更新編組到UI線程上。

+0

我得到了答案,感謝您的時間 – Olivia 2013-05-15 07:52:07

0

這很清楚,在您的控制檯應用程序中,您有一個Console.ReadLine在循環內部,使其停止,直到用戶輸入一個值並點擊Return。在表單應用程序中,您不需要執行while循環。用戶在文本框4中輸入一個值,然後單擊一個按鈕來處理該請求。

+0

是的,我明白了。謝謝你回答我。並解決我的問題 – Olivia 2013-05-15 07:50:46

0

在控制檯應用程序中,Main是針對該應用程序的入口點。所有程序都具有此功能,並在啓動可執行文件時由操作系統調用。

一旦被調用,它將像任何其他函數一樣被執行(從上到下),並且如果Main返回一個值,它會這樣做,並且OS終止程序。

爲了防止程序在一次運行後退出,通常使用while循環來確保未達到main功能的末尾(並執行return)。

Console.ReadLine阻塞功能 - 這意味着它不會讓下一行代碼執行,直到它已完成做什麼它(在本關懷,讀取用戶輸入)。

因此,您的控制檯應用程序一行一行地運行,直到它被輸入。然後它評估這個,輸出一個字符串,並永遠重複。

現在,在WinForms應用程序中,管理方式有點不同。 UI(按鈕,表單,文本框等)由主線程處理,這意味着您需要給它時間進行更新。通過在按鈕點擊功能中設置無限循環,您永遠不會將控制權返回給主線程,並且UI鎖定。

如果你只是想多次運行功能,刪除while循環和代碼將運行每次按鈕被點擊的時間。 Winforms將爲你處理。

如果仍然鎖定UI,代碼阻塞時間過長(按鈕事件內)。

如果是這樣,你必須做深入細緻的工作或者異步地(逐位)或卸載工作到另一個線程。看看使用backgroundWorkers確保UI不會凍結,並刪除無限循環。

+0

非常感謝你這個非常有用的答案。 – Olivia 2013-05-15 07:48:11

0
  1. 你在這兩個例子中無限循環的情況 - 讓你的程序是永遠無法優雅的退出,甚至在你的控制檯應用程序,你可能通過點擊它的「X」關閉控制檯形式退出,那是錯誤的..一個程序應該有一個邏輯實現,以允許用戶優雅地退出它。

  2. ,當你希望它是因爲它是絕不允許刷新你的用戶界面的第二個示例不工作的原因。這是一個不好的做法,把無限循環但向你證明,它實際上是沒有卡住或凍結,它只是無法刷新用戶界面在循環中添加另一個命令如下:

 
    : 
     listBox1.Items.Add("No Search Result Found"); 
     } 
     label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s"; 
     Application.DoEvents(); // add that line 
    } while (1==1); 

Application.DoEvents();停止執行循環,並允許圖形用戶界面線程更新窗口。

但正如我前面提到的 - 這不是開發一個應用程序的正確方法,更好的方法是簡單地刪除該循環,如下所示:

 
private void button6_Click(object sender, EventArgs e) 
    { 
     if (t == null) 
     { 
      MessageBox.Show("Click on LoadFile Button,Please."); 
      return; 
     } 
     if (textBox4.Text == "") 
     { 
      MessageBox.Show("Enter your Boolean Query"); 
      return; 
     } 
     listBox1.Items.Clear(); 
     DateTime dt = DateTime.Now; 

     List lst = t.ProcessQuery(textBox4.Text); 
     count = 0; 
     if (lst != null) 
     { 
      foreach (int a in lst) 
      { 
       listBox1.Items.Add(t.documentContentList[count]); 
      } 
      count++; 
     } 
     else 
     { 
      listBox1.Items.Add("No Search Result Found"); 
     } 
     label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s"; 
    } 

現在,每次單擊該按鈕它會調用你的事件處理程序,當事件處理程序退出時,用戶界面將自動更新。因爲你的表單是從System.Windows.Form類派生的,所以保留Windows消息泵的指令一直持續到用戶單擊'x'爲止已經在父類中爲你實現了,那就是System.Windows.Form類的表單源自於。

當然,在控制檯應用程序中,情況並非如此。

+0

你是對的我不需要任何{while()循環。謝謝 – Olivia 2013-05-15 08:15:24

相關問題