为什么有时会收到此NullReferenceException?

这是一段有时会引发异常的代码:

Pendings = ClientCode.PendingOrders.Select(x => new DisplayPending()
{
    ItemCode = ClientCode.Items.First(y => y.Id == x.ItemCode).Id,ItemName = ClientCode.Items.First(y => y.Id == x.ItemCode).Name,OrderNo = x.BuyOrderNo == 0 ? x.SellOrderNo : x.BuyOrderNo,OrderType = x.OrderType == OrderType.Buy ? "Buy" : "Sell",PartyCode = x.PartyCode,Price = x.Price,Quantity = x.Quantity
});

这是消息:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

x was null.

PendingOrdersObservableCollection,它有500多个项目。

编辑

这是我填充扩展ObservableCollection的方式:

public class AsyncObsetion<T> : ObservableCollection<T>
{
    SynchronizationContext context = SynchronizationContext.Current;
    readonly object _lock = new object();
    public AsyncObsetion() { BindingOperations.EnableCollectionSynchronization(this,_lock); }
    public AsyncObsetion(IEnumerable<T> list) : base(list) { BindingOperations.EnableCollectionSynchronization(this,_lock); }

    void RaiseCollectionChanged(object param) => base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
    void RaisePropertyChanged(object param) => base.OnPropertyChanged((PropertyChangedEventArgs)param);

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (SynchronizationContext.Current == context) RaiseCollectionChanged(e);
        else context.Send(RaiseCollectionChanged,e);
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (SynchronizationContext.Current == context) RaisePropertyChanged(e);
        else context.Send(RaisePropertyChanged,e);
    }

    public void InsertRange(IEnumerable<T> items)
    {
        this.CheckReentrancy();
        foreach (var item in items)
            this.Items.Add(item);
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedaction.Reset));
    }
}

Client连接到Server时,它将发送6个byte[],它们被添加到名为AsyncObsetion<T>Items,{{ 1}},NewsCollectionIssuedBuyOrdersSellOrdersPendingOrders在客户端。这段代码负责处理客户端从服务器获取的ExecutedOrders

MyExecutedOrders

byte[]是一个事件,当它被触发时,客户端开始从var tasks = new List<Task>(); tasks.Add(Task.Run(() => { for (int i = 0; i < header.ItemSize; i += Constants.itemSize) { var item = PacMan<ItemStruct>.Unpack(itemArray.Skip(i).Take(Constants.itemSize).ToArray()); Items.Add(new Item() { Id = item.Id,Name = item.Name,Cap = item.Cap,Floor = item.Floor,Mid = item.Floor + ((item.Cap - item.Floor) / 2),Securities = item.Securities,Owners = item.Owners,Govt = item.Govt,Institutions = item.Institutions,Foreign = item.Foreign,Public = item.Public,PerSecurity = PacMan<PerSecurityFinancialsStruct>.ArrayToList<PerSecurityFinancials>(item.PerSecurity),Dividends = PacMan<DividendStruct>.ArrayToList<Dividend>(item.Dividends),InitialSecurity = item.InitialSecurity }); } }).ContinueWith(t => { if (header.HasExecuted) GetExOrders(header.ExecutedSize,execArray); if (header.Hasnews) AddNews(newsArray.ToArray()); })); tasks.Add(Task.Run(() => { if (header.HasBuy) GetOrders(header.BuySize,buyArray,"buy"); })); tasks.Add(Task.Run(() => { if (header.HasSell) GetOrders(header.SellSize,sellArray,"sell"); })); tasks.Add(Task.Run(() => AddIssue(issueArray.ToArray()))); Task.WaitAll(tasks.ToArray()); hasReceivedData = true; App.Current.Dispatcher.Invoke(() => CommandManager.InvalidateRequerySuggested()); OnConnected(); OrderVM.ItemCode = Items.First().Id; e.Completed += Receive; e.SetBuffer(headerBuffer,headerBuffer.Length); if (!e.acceptsocket.ReceiveAsync(e)) Receive(null,e); OnConnected()组成的Pendings中创建PendingOrders的过程。我认为这是问题所在,我相信有时buyArray会在sellArray之前被解雇。如果有人感兴趣,这就是OnConnected()的作用:

Task.WaitAll(tasks.ToArray())

这里是GetOrders

void GetOrders(int size,IEnumerable<byte> array,string type)
{
    var orderList = new List<AllOrder>();
    var pendingList = new List<AllOrder>();

    for (int i = 0; i < size; i += Constants.orderSize)
    {
        var order = PacMan<AllOrderStruct>.Unpack(array.Skip(i).Take(Constants.orderSize).ToArray());
        AddInitNewOrder(order,orderList,pendingList);
    }
    if (type == "buy") CheckNumberAndAdd(orderList,BuyOrders);
    else CheckNumberAndAdd(orderList,SellOrders);
    CheckNumberAndAdd(pendingList,PendingOrders);
}

这是AddInitNewOrder

void AddInitNewOrder(AllOrderStruct order,List<AllOrder> orders,List<AllOrder> pendingOrders)
{
    var o = new AllOrder();
    o.action = order.action;
    o.OrderType = order.OrderType;
    o.ItemCode = order.ItemCode;
    o.BrokerName = order.BrokerName;
    o.PartyCode = order.PartyCode;
    o.Price = order.Price;
    o.Quantity = order.Quantity;
    o.BuyOrderNo = order.BuyOrderNo;
    o.SellOrderNo = order.SellOrderNo;
    orders.Add(o);
    if (o.BrokerName == BrokerName) pendingOrders.Add(o);
}

如果我在CheckNumberAndAdd函数中设置brekpoint,我看到void CheckNumberAndAdd<T>(List<T> normList,AsyncObsetion<T> obsList) { var count = normList.Count; if(count > 50) { obsList.InsertRange(normList.Take(count - 50)); var remaining = normList.Skip(count - 50).ToList(); for (int i = 0; i < remaining.Count; i++) obsList.Insert(0,remaining[i]); } else for (int i = 0; i < count; i++) obsList.Insert(0,normList[i]); } GetOrders中获得483个项目,而从pendingList中获得494个项目,因此我总共有977个项目。因此,我应该始终在sellArray中获得977个项目,但是如果我在buyArray中删除brekpoint并在PendingOrders方法中设置了断点,则该方法已挂接到该事件GetOrders中,我看到{{ 1}}有时少于977个项目。

je8600 回答:为什么有时会收到此NullReferenceException?

正如@BionicCode所说,集合中只有一些null元素。

只需使用.Where(x != null)或类似的方法过滤掉它们。
尽管这可以解决问题,但是通常未检测到的空引用是有关代码中星期数的提示。

请考虑加强您的null检查策略,以免将来出现这些错误。使用相同的框架,您可以对可为空的对象执行检查,从而使代码更简洁,更健壮。

https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/february/essential-net-csharp-8-0-and-nullable-reference-types

,

解决此问题的一种方法是像这样包装fPIE方法的最后三行:

static

这有效。

本文链接:https://www.f2er.com/2866562.html

大家都在问