在winform应用里,有DataGridView,用BindingList 做数据源。
MotionList = new List<Motion>();
MotionBList = new BindingList<Motion>(MotionList);
DataGridViewMotion.DataSource = MotionBList;
DataGridViewMotion.RowHeadersVisible = false;
DataGridViewMotion.AllowUserToAddRows = false;
DataGridViewMotion.ReadOnly = true;
Where
public class Motion
{
public string StartTime { get; set; }
public string EndTime { get; set; }
public string StartPos { get; set; }
public string EndPos { get; set; }
}
用 MotionBList.Add()
MotionBList.RemoveAt()
这两方法来更新DataGridViewMotion. 只有如下用法,都用SyncContext在UI线程执行了:
SyncContext = WindowsFormsSynchronizationContext.Current;
SyncContext.Post(new SendOrPostCallback((_) =>
{
if (MotionBList.Count > 600)
{
for (int i = 0; i < 100; i++)
{
MotionBList.RemoveAt(0);
}
}
MotionBList.Add(MakeMotion(...));
}), null);
private Motion MakeMotion(string a, string b)
{
return new Motion() {StartPos = a, EndPos = b};
}
大部分时候都正常工作,但是 MotionBList.Add(MakeMotion(...))
时有小概率报错, 报错信息如下:
Application_ThreadException System.ArgumentOutOfRangeException: 107 的值对于 indexStart无效, indexStart 必须小于等于 93.
在 System.Windows.Forms.DataGridViewRowCollection.GetPreviousRow(Int32 indexStart, DataGridViewElementStates includeFilter)
在 System.Windows.Forms.DataGridViewRowCollection.GetPreviousRow(Int32 indexStart, DataGridViewElementStates includeFilter, DataGridViewElementStates excludeFilter)
在 System.Windows.Forms.DataGridView.CorrectRowFrozenState(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, Index32 anticiptedRowIndex)
在 System.Windows.Forms.DataGridView.OnInsertingRow(Int32 rowIndexInserted, DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, Point& newCurrentCell, Boolean firstInsertion, Int32 insertionCount, Boolean force)
在 System.Windows.Forms.DataGridViewRowCollection.InsertInternal(Int32 rowIndex, DataGridViewRow dataGridViewRow, Boolean force)
在 System.Windows.Forms.DataGridViewRowDataCollection.ProcessListChanged(ListChangedEventArgs e)
在 System.Windows.Forms.DataGridViewRowDataCollection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e)
在 System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e)
at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
在 System.ComponentModel.BindingList~1.OnListChanged(ListChangedEventArgs e)
在 System.ComponentModel.BindingList~1.FireListChanged(ListChangedType type, Int32 index)
在 System.ComponentModel.BindingList~1.InsertItem(Int32 index, T item)
在 System.Collections.ObjectModel.Collection~1.Add(T item)
在 MotionBList.Add(MakeMotion(...))
上面的异常是 Programe.cs 里的代码捕获到的
Application.ThreadException += Application_ThreadException; //只捕获UI线程的错误
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show($"Application_ThreadException {e.Exception}");
}
你搜一下在哪调用了这个方法吧:
GetPreviousRow
GetPreviousRow是System.Windows.Forms.dll里面的函数,是MotionBList.Add函数触发的。
用同步的试试,如果同步的方法没问题,那可能是你代码其他地方有操作这个集合,导致下标索引在不同的地方同时被消耗了。
把异常捕获事件注释,看下实际在哪报错
– 拒绝访问 3年前