【问题标题】:BindingList.Clear performed Async causes DataGridView System.IndexOutOfRangeExceptionBindingList.Clear 执行异步导致 DataGridView System.IndexOutOfRangeException
【发布时间】:2016-12-18 07:26:49
【问题描述】:

我需要一些帮助。 我有一个 DataGridView,它只是一个绑定到 BindingList 的只读。 我首先为新列表设置数据源,然后将项目添加到列表中。 列是自动生成的。 当我需要重新加载页面时,我只需清除列表并再次添加项目。

如果我使用 UI 重新加载页面同步,它可以正常工作,但如果我启动一项任务并执行此操作,则在 BindingList 上调用 Clear() 会失败并出现异常:

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)

【问题讨论】:

  • BindingList 不是线程安全的。这就是它失败的原因。

标签: c# datagridview bindinglist


【解决方案1】:

这是多线程问题。

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);
    }
}

【讨论】:

  • 你为什么这么认为?可以将 async 与 MVVM 或类似模式一起使用。但是你应该小心处理跨线程操作。此外,您通常不需要从工作线程更新数据绑定集合。如果您的任务从 Web 服务或类似服务中获取集合,则在每个项目上重新绘制绑定控件是低效的。
猜你喜欢
  • 1970-01-01
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多