2009-09-02 4 views
1

나는 진행중인 WinForm 앱을 테스트하기위한 간단한 프레임 워크를 작성 중이다. Application.OpenForms를 사용하여 현재 테스트 단계에서 변경해야하는 컨트롤을 찾습니다. 그러나 때때로 (다른 스레드에 의해) 컬렉션이 수정 된 오류가 발생합니다. 이 컬렉션을 잠그면 일반 UI 스레드 (새 양식 열기 등)가 방해받지 않도록 할 수 있습니까?어떻게 Application.OpenForms를 잠글 수 있습니까?

답변

2

이 속성을 잠그는 빌드 인 솔루션은 없다고 생각합니다. 이 아닌을 사용하면 수정 된 컬렉션을 찾는 반복자로 인해 발생하는 예외를 방지하기 위해 foreach -loop을 사용하는 것이 좋습니다. while -loop (차단 조건은 한 번만 평가되므로 for -loop이 아님)을 사용하십시오.

처리 할 다른 양식이 있다는 것을 확인한 후 양식이 목록에서 제거되고 ArgumentOutOfRangeException이 표시 될 위험이 여전히 있습니다. 이 상황을 정상적으로 처리해야합니다.

Int32 index = 0; 
while (index < Application.OpenForms.Count) 
{ 
    try 
    { 
     // Try to copy the form because the index may be or may 
     // become invalid. 
     Form form = Application.OpenForms[index]; 

     // Do stuff with the form. 
    } 
    catch (ArgumentOutOfRangeException exception) 
    { 
     // Handle no longer valid index. 
    } 

    index++; 
} 

이것은 완벽하지 않지만 지금은 더 나은 해결책을 생각할 수 없습니다. 예를 들어 양식 5에있을 수 있으며 일시 중지되고 응용 프로그램이 처음 다섯 개의 양식 중 일부를 닫습니다. 결과적으로 처리되지 않은 양식은 앞쪽으로 이동하고 스레드는 양식 6에서 계속 될 때 코드에 의해 무시됩니다.

어떤 시점에서 모든 양식을 처리해야하는 경우 (응용 프로그램 상태의 스냅 샷과 같이) foreach -loop을 사용하는 유일한 해결책 일 수 있으며, 실제로 전체 컬렉션을 반복하지 않고 관리 할 때까지 다시 시도하십시오. 예외. 물론 폼이 매우 빠른 속도로 열리고 닫히는 경우 또는 반복 코드에 따라 절대 발생하지 않는 명백한 위험이 있습니다.

+0

그게 거의 내가 원한 것이 아니지만, 좋은 해결책이없는 것 같습니다. 건배. – Grzenio

0

Application.OpenForms에 대해 잊어 버리고 대신 관리되지 않는 WinApi를 사용하십시오.

static IEnumerable<Form> EnumOpenForms() 
{ 
    foreach (System.Diagnostics.ProcessThread thread in System.Diagnostics.Process.GetCurrentProcess().Threads) 
    { 
     List<IntPtr> hWnds = new List<IntPtr>(); 
     EnumThreadWindows(thread.Id, (hWnd, param) => { hWnds.Add(hWnd); }, IntPtr.Zero); 
     foreach(IntPtr hWnd in hWnds) 
     { 
      Form form = Control.FromHandle(hWnd) as Form; 
      if (form != null) 
      { 
       yield return form; 
      } 
     } 
    } 
} 

[System.Runtime.InteropServices.DllImport("user32.dll")] 
static extern bool EnumThreadWindows(int dwThreadId, EnumWindowProc lpEnumFunc, IntPtr lParam); 

delegate void EnumWindowProc(IntPtr hWnd, IntPtr parameter); 
관련 문제