2017-07-09 321 views
3

我正在寫一個WinForms C#程序。C#ArgumentOutOfRangeException關閉窗體時

我正在嘗試關閉除主窗體FrmMain之外的所有窗體。

我必須隱藏我的主窗體。

我通過打開兩種形式來製作這個。一個用我的主窗體,另一個用ShowDialog()方法顯示。

在我的機器上執行此代碼時,它似乎應該正確關閉所有窗體。出於某種原因,當我沒有設置斷點並運行這段代碼時,我得到一個ArgumentOutOfRangeException,因爲變量i達到了它的位置,它是-1。當我設置斷點時,慢慢地遍歷每一段代碼就可以正常工作。

因爲我有i >= 0條件,所以for循環繼續一直持續到i達到-1沒有任何意義。

有人可以向我解釋爲什麼當我不使用斷點時i的索引得到-1,但當我使用斷點並單獨遍歷循環的每一行時,得到0

可以做些什麼來解決這個問題?

在此先感謝。

  for (int i = Application.OpenForms.Count - 1; i >= 0; i--) 
      { 
       if (Application.OpenForms[i] is FrmMain) 
       { 
        Application.OpenForms[i]?.BeginInvoke((MethodInvoker)delegate 
        { 
         Application.OpenForms[i]?.Hide(); 
        }); 
       } 
       else 
       { 
        Application.OpenForms[i]?.BeginInvoke((MethodInvoker)delegate 
        { 
         Application.OpenForms[i]?.Dispose(); 
        }); 
       } 
      } 

編輯:

我防止得到ArgumentOutOfRangeException是通過增加另一個變量內部的for循環的方式。 這是我改變的代碼。

  for (int i = Application.OpenForms.Count - 1; i >= 0; i--) 
      { 
       int i1 = i; 
       if (Application.OpenForms[i] is FrmMain) 
       { 
        Application.OpenForms[i]?.BeginInvoke((MethodInvoker)delegate 
        { 
         Application.OpenForms[i1]?.Hide(); 
        }); 
       } 
       else 
       { 
        Application.OpenForms[i]?.BeginInvoke((MethodInvoker)delegate 
        { 
         Application.OpenForms[i1]?.Dispose(); 
        }); 
       } 
      } 
+2

搜索術語「C#進行封」 –

+0

何處,何時,多少次你叫這個代碼? –

+0

@AfshinAghazadeh它只在一個新線程的類中調用過一次 – Ben

回答

1

從本質上講,當條件是假的for僅環終止,這意味着i有去-1之前將停止。請參閱 When does iteration variable in for loop increment應該提供一個很好的解釋。

與您使用BeginInvoke,基本上移動執行到一個單獨的線程的事實相結合(這意味着它的執行可能會推遲),並且i是捕獲變量完全有可能爲i-1Dispose()是調用。

當你有適當的斷點時,你可能會減慢主線程執行的速度,以至於所有單獨的線程都以預期的順序運行,所以你不會看到問題。

您可以瞭解拍攝的變量在這裏:What are 'closures' in .NET?

+1

我不認爲「這是完全可能的」在這裏足夠強大。我認爲這確實是這樣發生的。 – Enigmativity

+0

謝謝。這幫了我 – Ben