2014-04-07 2 views
0

스레드 안전 모드에서 C# WinForms ComboBox.Items 컬렉션 (예제에서는 아래 코드 참조)을 반복하는 방법은 무엇입니까? 컬렉션을 사용하면 잠금을 사용할 수 있지만 데이터 바인딩 소스에서 업데이트되므로 comboBox.Items 컬렉션을 제어하지 않습니다.이 메서드를 재사용 가능한 상태로 유지하려면 특정 데이터 바인딩 소스와 상호 작용할 수 없습니다. 이 코드에서). comboBox.Items.CopyTo 메서드가 있지만 먼저 배열을 만들어야하고 배열을 만들고 복사를 수행하는 횟수가 달라질 수 있습니다?스레드 안전 모드에서 CombBox.Items 반복 처리

어떤 조언을 주셔서 감사합니다.

private void SetComboBoxWidth(ComboBox comboBox, bool setDropDownWidth) 
{ 
    int maxWidth = 0; 
    using (Graphics graphics = comboBox.CreateGraphics()) 
    { 
     foreach (object item in comboBox.Items) 
     { 
      int curWidth = TextRenderer.MeasureText(graphics, item.ToString(), comboBox.Font).Width; 
      if (curWidth > maxWidth) 
      { 
       maxWidth = curWidth; 
      } 
     } 
    } 
    maxWidth += SystemInformation.VerticalScrollBarWidth; 

    if (setDropDownWidth) 
    { 
     comboBox.DropDownWidth = maxWidth; 
    } 
    else 
    { 
     comboBox.Width = maxWidth; 
    } 
} 

편집 : 위의 코드는 발생 : {System.InvalidOperationException} 컬렉션이 변경되었다 열거 연산이 실행되지 않을 수 있습니다.

는 콤보 상자가 함께 설립되었다 :

myComboBox.ComboBox.DataSource = new BindingList<IMyInterface>(); 

그리고 호출 체인은 다음과 같습니다 MyForm.OnLoad-> MyForm.Setup-> MyForm.SetComboBoxWidth

편집 2 : 변경된 예제 코드하지에 루프 동안 ComboBox를 변경하십시오 (이전 버전은 각 반복에서 Width를 잠재적으로 조정합니다).

+0

WinForms는 단일 스레드입니다. 다른 스레드에서 직접 아무것도하지 않으면 항상 스레드로부터 안전합니다. 즉, 다른 스레드에서 데이터 소스 업데이트가 수행 되더라도 올바른 UI 스레드로 업데이트가 전달됩니다. 물론 foreach 루프 내에서 comboBox.Items를 변경하면 열거는 실패하지만 어떤 열거 형에서도 마찬가지입니다 ... –

+0

@Adriano 위의 예제 코드는 throw됩니다. 컬렉션이 수정되었습니다. 열거 연산이 실행되지 않을 수 있습니다. {System.InvalidOperationException} – FPike

+0

정확히 무엇을 던지나요? - 편집 : 너무 느린 타이핑 – toATwork

답변

0

은 여러 스레드에서 UI를 업데이트하지 않아야합니다. 이 규칙을 따르는 경우 스레드 보안이 "주 스레드"에 의해서만 업데이트되므로 걱정할 필요가 없습니다.

다른 스레드에서 UI를 업데이트해야하는 경우 Control.Invoke 또는 Control.BeginInvoke을 사용하여 컨트롤을 UI 스레드로 전달해야합니다.

0

다른 사람에게이 문제가 발생하는 경우 내 자신의 질문에 대답하지만 일어난 일에 대해 완전히 이해하지 못했습니다.

BindingList에 저장된 IMyInterface 개체에도 INotifyPropertyChanged가 구현됩니다. 백그라운드 스레드는 IMyInterface 객체의 속성을 변경하여 INotifyPropertyChanged.PropertyChanged를 발생시킬 수 있습니다. BindingList DataSource의 개체 속성이 변경되면 ComboBox에서 해당 목록을 다시 만듭니다 (I think 어쨌든 발생합니다. 확실하지 않음). foreach가 iterating하는 동안 이런 일이 발생하면 InvalidOperationException이 Throw됩니다.

필자는 필요한 경우 OnListChanged를 재정의하는 BindingList의 하위 클래스를 만들어이 문제를 해결했습니다. 이것은 문제를 해결 한 것 같습니다.

올바른 방향으로 답변하고 댓글을 달고 지적한 사람들에게 감사드립니다.