2016-12-18 10 views
0

도움이 필요합니다. BindingList에 읽기 전용으로 바인딩되는 DataGridView가 있습니다. 먼저 새 목록에 대한 데이터 소스를 설정하고 항목을 목록에 추가합니다. 열이 자동으로 생성됩니다. 페이지를 새로 고침해야 할 때 목록을 지우고 항목을 다시 추가하면됩니다.BindingList.Clear 수행으로 인해 DataGridView가 발생합니다. System.IndexOutOfRangeException

나는 그것이 잘 작동하지만 작업을 시작하고는 바인딩에 지우기()를 호출, 그것을 할 경우 예외로 실패 UI와 페이지 동기화 다시로드를 수행하는 경우 :

System.IndexOutOfRangeException was unhandled 
    HResult=-2146233080 
    Message=Index 0 does not have a value. 
    Source=System.Windows.Forms 
    StackTrace: 
     at System.Windows.Forms.CurrencyManager.get_Item(Int32 index) 
     at InCare.UserControls.DataGridViewItemWrapper.DataGridViewOnRowsAdded(Object sender, DataGridViewRowPostPaintEventArgs args) in C:\ws\Source\Repos\incare\Src\InCare.UserControls\DataGridViewItemWrapper.cs:line 40 
     at System.Windows.Forms.DataGridViewRowPostPaintEventHandler.Invoke(Object sender, DataGridViewRowPostPaintEventArgs e) 
     at System.Windows.Forms.DataGridView.OnRowPostPaint(DataGridViewRowPostPaintEventArgs e) 
     at System.Windows.Forms.DataGridView.PaintRows(Graphics g, Rectangle boundingRect, Rectangle clipRect, Boolean singleHorizontalBorderAdded) 
     at System.Windows.Forms.DataGridView.PaintGrid(Graphics g, Rectangle gridBounds, Rectangle clipRect, Boolean singleVerticalBorderAdded, Boolean singleHorizontalBorderAdded) 
     at System.Windows.Forms.DataGridView.OnPaint(PaintEventArgs e) 
     at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer) 
     at System.Windows.Forms.Control.WmPaint(Message& m) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
+0

'BindingList'이 스레드 안전하지 않습니다. 그것이 실패하는 이유입니다. –

답변

2

이가 멀티 스레딩 문제.

BindingList은 스레드로부터 안전하지 않습니다. 작업자 스레드에서 작동하는 작업에서이를 지우려고 할 때 DGV은 UI 스레드에서이 스레드를 읽습니다.

코드를 게시하지는 않았지만 기본 접근 방식은 작업 내에서 일부 컬렉션을 빌드 한 다음이 컬렉션을 반환하여 BindingList 콘텐츠를 대체합니다.

배경 스레드에서 BindingList을 변경하려고하지 마십시오

private async Task<IList<SomeDataItem> GetDataItemsAsync() 
{ 
    // do some work in background, e.g. call web service or database 
    // ... 
    return dataItems; 
} 

pirvate async void HandleRefreshButtonClick(object sender, EventArgs e) 
{ 
    var dataItems = await GetDataItemsAsync(); 

    // since we didn't call ConfigureAwait(false) for task, 
    // the rest of method will run on UI thread 
    bindingList.Clear(); 

    foreach (var item in dataItems) 
    { 
     bindingList.Add(item); 
    } 
} 
+0

그래서 비동기 MVVM이 제대로 작동하지 않을 것입니다 :(. –

+0

왜 그렇게 생각합니까? MVVM 또는 유사한 패턴과 비동기를 사용하는 것이 좋지만, 크로스 스레드 작업을 신중하게 다루어야합니다. 작업 스레드에서 데이터 바운드 컬렉션 작업이 웹 서비스 또는 유사하게 컬렉션을 가져 오는 경우 각 항목의 바운드 컨트롤을 다시 그리는 것이 비효율적입니다. – Dennis