C# ObservableCollection上的FirstOrDefault获取ArgumentOutOfRange异常
我有一个可观察的集合C# ObservableCollection上的FirstOrDefault获取ArgumentOutOfRange异常,c#,linq,C#,Linq,我有一个可观察的集合CurrentItemSource,当我试图调用FirstOrDefault时,我在其中得到了一个ArgumentOutOfRangeException CommandViewModel item = CurrentItemSource?.FirstOrDefault(); 我不明白这怎么可能,因为描述了可以从FirstOrDefault引发的唯一异常是ArgumentNullException public bool MoveNext() { List<T&
CurrentItemSource
,当我试图调用FirstOrDefault
时,我在其中得到了一个ArgumentOutOfRangeException
CommandViewModel item = CurrentItemSource?.FirstOrDefault();
我不明白这怎么可能,因为描述了可以从FirstOrDefault
引发的唯一异常是ArgumentNullException
public bool MoveNext()
{
List<T> list = this.list;
// This if condition might be entered into by a second thread
// after the first thread modified the list
if ((this.version == list._version) && (this.index < list._size))
{
// This line is contentious and might be
// the source of your exception.
this.current = list._items[this.index];
this.index++;
return true;
}
return this.MoveNextRare();
}
我得到的例外情况是:
ArgumentOutOfRangeException[2]:索引滞后于Bereichs。他没有底片,克莱纳也没有。
参数名称:索引
这是怎么发生的?有没有可能解决这个问题
我在构造函数中实例化CurrentItemSource
:
CurrentItemSource = new ObservableCollection<CommandViewModel>();
if (Application.Current != null)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
CurrentItemSource.EnableCollectionSynchronization();
}));
}
堆栈跟踪:
Stacktrace [2]
bei System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
bei System.Collections.Generic.List1.get_Item(Int32 index)
bei System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source)
bei Gui.ViewModels.ComboBoxViewModel.SetDisplayedText(String comboBoxText) in D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 707.
bei Gui.ViewModels.ComboBoxViewModel.set_ComboBoxText(String value) in D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 209.
bei Gui.ViewModels.OutputViewModel.CreateContextMenu(ComboBoxViewModel comboBox) in D:\workspace\Gui\ViewModels\OutputViewModel.cs:Zeile 160.
bei Gui.ViewModels.ComboBoxViewModel.CreateContextMenuAsync() in D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1051.
bei Gui.ViewModels.ComboBoxViewModel.<BuildCurrentItemSource>b__135_0() in D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1031.
bei System.Threading.Tasks.Task.Execute()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
bei Gui.ViewModels.ComboBoxViewModel.<BuildCurrentItemSource>d__135.MoveNext() in D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1031.
Stacktrace[2]
bei System.ThrowHelper.ThrowArgumentOutOfRangeException(异常参数,异常资源)
bei System.Collections.Generic.List1.get_项(Int32索引)
bei System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1源)
bei Gui.ViewModels.ComboBoxViewModel.SetDisplayedText(字符串comboBoxText)位于D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 707中。
bei Gui.ViewModels.ComboBoxViewModel.set_ComboBoxText(字符串值)位于D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 209中。
bei Gui.ViewModels.OutputViewModel.CreateContextMenu(ComboBoxViewModel comboBox)位于D:\workspace\Gui\ViewModels\OutputViewModel.cs:Zeile 160中。
bei Gui.ViewModels.ComboBoxViewModel.CreateContextMenuAsync()位于D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1051中。
bei Gui.ViewModels.ComboBoxViewModel.b_uu135_0()位于D:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1031中。
bei System.Threading.Tasks.Task.Execute()
---这是一个非常有趣的故事---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务)
bei System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
d:\workspace\Gui\ViewModels\ComboBoxViewModel.cs:Zeile 1031中的bei Gui.ViewModels.ComboBoxViewModel.d__135.MoveNext()。
异常原因的简要总结
您的代码正在引发异常,因为线程不安全地访问ObservableCollection
表示的底层IList
不提供自身的线程安全性。它只保证CustomView
将使用与您提供的相同的同步技术,以线程安全的方式访问集合的元素
请注意,文档内容如下:
而您必须同步应用程序对
集合,您还必须保证从WPF(特别是
从CollectionView)参与相同的同步
机制。您可以通过调用EnableCollectionSynchronization来实现这一点
方法
解决方案
由于您正在使用,因此需要通过lock
语句(或System.Threading.Monitor
类)保护对可观察集合的访问
因此,您必须这样做:
// class level field
private object _lock = new object();
...
CommandViewModel item = null;
lock(_lock)
{
item = CurrentItemSource?.FirstOrDefault();
}
有关异常原因的更多解释
异常的来源很可能是以下两个地方之一。如果发布堆栈跟踪,您可能会看到它的路径中有两个代码路径之一:
One:System.Linq.Enumerable.FirstOrDefault()
检查基础列表的可空性然后索引的if
条件
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
{
IList<TSource> list = source as IList<TSource>;
// The following is re-entrant by multiple threads
// in a thread-unsafe manner.
if (list != null)
{
if (list.Count > 0)
{
// This code is contentious and most likely
// the place where your code bombs.
return list[0];
}
}
else
...
正如您现在发布的堆栈跟踪一样,您可以看到它在我上面列出的两个可能的代码路径中的第一个路径中爆炸。也就是说,在
系统.Linq.Enumerable.FirstOfDefault
方法体中。异常原因的简要摘要
您的代码正在引发异常,因为线程不安全地访问ObservableCollection
表示的底层IList
不提供自身的线程安全性。它只保证CustomView
将使用与您提供的相同的同步技术,以线程安全的方式访问集合的元素
请注意,文档内容如下:
而您必须同步应用程序对
集合,您还必须保证从WPF(特别是
从CollectionView)参与相同的同步
机制。您可以通过调用EnableCollectionSynchronization来实现这一点
方法
解决方案
由于您正在使用,因此需要通过lock
语句(或System.Threading.Monitor
类)保护对可观察集合的访问
因此,您必须这样做:
// class level field
private object _lock = new object();
...
CommandViewModel item = null;
lock(_lock)
{
item = CurrentItemSource?.FirstOrDefault();
}
有关异常原因的更多解释
异常的来源很可能是以下两个地方之一。如果发布堆栈跟踪,您可能会看到它的路径中有两个代码路径之一:
One:System.Linq.Enumerable.FirstOrDefault()
检查基础列表的可空性然后索引的if
条件
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
{
IList<TSource> list = source as IList<TSource>;
// The following is re-entrant by multiple threads
// in a thread-unsafe manner.
if (list != null)
{
if (list.Count > 0)
{
// This code is contentious and most likely
// the place where your code bombs.
return list[0];
}
}
else
...
正如您现在发布的堆栈跟踪一样,您可以看到它在我上面列出的两个可能的代码路径中的第一个路径中爆炸。也就是说,在
System.Linq.Enumerable.FirstOfDefault
方法体中。CurrentItemSource是什么类型的?CurrentItemSource是一个ObservableCollection您周围还有一些代码吗?那么XAML文件呢?@SimonG你能把代码发到你第一次登录的地方吗