同一应用程序的多个实例引发StackOverflow异常

问题描述 投票:-2回答:2

在我的解决方案中,我有3个主要项目(ServerClientSpecial Client)。在我的测试环境中,(1)Special Client仅每5秒显示一次购买/出售/已执行订单的数量,(2)Client提交购买/出售订单,(3)Server处理客户提交的订单,发送回ClientSpecial Client。如果我通过按Ctrl + F5启动所有3个应用程序,并让Client每10毫秒提交一个订单,那么所有这些应用程序都可以正常工作,并且在Windows Task Manager上我观察到内存Client的使用率在115MB到320MB之间波动,没有一个崩溃(我已经测试了很长时间)。

[如果我从Client启动另外2个../Client/bin/Debug/...(总共3个Client实例,分别是1 Special Client和1 Server),然后让每个Client每秒提交20个订单,那么它也可以正常工作(不确定Client的性能可能会略有下降)。但是,如果我从Client启动第四个../Client/bin/Debug/...并让他们每个人每秒提交20个订单,那么我最终会在其中一个StackOverflow exception上获得Client

因此,简而言之,一个Client可以每秒提交100个订单,并从Server中取回所有订单,并在一个中等复杂的UI上显示信息,而在单个计算机上没有麻烦,三个Client一起可以处理60订单/秒,但4 Client不能同时处理80订单/秒!

为什么?

编辑

这是我在“呼叫堆栈”窗口中收到的消息:

    [External Code] 
>   Client.dll!Client.AsyncObsetion<Data.AllOrder>.OnPropertyChanged(System.ComponentModel.PropertyChangedEventArgs e) Line 29  C#
    [External Code] 
    Client.dll!Client.ClientCode.UpdateOrderOnExecution(Data.AllOrderStruct order) Line 431 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 390 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
        .
        .
        .
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
    Client.dll!Client.ClientCode.Receive(object sender, System.Net.Sockets.SocketAsyncEventArgs e) Line 402 C#
    [External Code]     

第29行C#引用了这段代码的这一行else context.Send(RaisePropertyChanged, e);

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)
    {
        CheckReentrancy();
        foreach (var item in items) Items.Add(item);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

但是我该活动的代码中没有任何订阅者!第431行引用此行if (order.ExType == ExecutionType.Full) list.Remove(o);此段代码:

void UpdateOrderOnExecution(AllOrderStruct order)
{
    bool buyOrder = order.OrderType == OrderType.Buy;
    var list = buyOrder ? BuyOrders : SellOrders;
    var o = buyOrder ? list.Where(x => x.BuyOrderNo == order.BuyOrderNo).First() : list.Where(x => x.SellOrderNo == order.SellOrderNo).First();
    o.ExType = order.ExType;

    if (order.ExType == ExecutionType.Full) list.Remove(o);
    else
    {
        var index = list.IndexOf(o);
        o.Quantity -= order.QtyTraded;
        list[index] = o;
    }
    AddExecutedOrder(order);
    if (order.BrokerBought == BrokerName || order.BrokerSold == BrokerName) UpDatePendingOrders(o);
    App.Current.Dispatcher.Invoke(CommandManager.InvalidateRequerySuggested);
}

第390行指向此代码行case Data.Action.Execute: UpdateOrderOnExecution(order); break;,而402指向此代码段的此行if (!e.AcceptSocket.ReceiveAsync(e)) Receive(null, e);

void Receive(object sender, SocketAsyncEventArgs e)
{
    if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
    {
        var data = PacMan<MessageHeader>.Unpack(e.Buffer);
        if (data.Type == Message.Trade)
        {
            e.SetBuffer(orderBuffer, 0, orderBuffer.Length);
            e.AcceptSocket.Receive(e.Buffer);
            var order = PacMan<AllOrderStruct>.Unpack(e.Buffer);

            switch (order.Action)
            {
                case Data.Action.Add: AddNewOrder(order); break;
                case Data.Action.Delete: RemoveOrder(order); break;
                case Data.Action.Modify: ModifyOrder(order); break;
                case Data.Action.Execute: UpdateOrderOnExecution(order); break;
            }
        }
        else
        {
            SetBuffer(e, data.Size);
            e.AcceptSocket.Receive(e.Buffer);
            var array = e.Buffer.ToArray();
            Task.Run(() => AddNews(array));
        }

        e.SetBuffer(headerBuffer, 0, headerBuffer.Length);
        if (!e.AcceptSocket.ReceiveAsync(e)) Receive(null, e);
    }
    else Disconnect4mServer(null);
}
c# wpf stack-overflow
2个回答
1
投票

您应该使用多线程方法,因为您正在同时使用3个项目,请尝试使用多线程并让CPU为您处理它,因为我没有在代码中看到任何问题,所以>


0
投票

[Charles

© www.soinside.com 2019 - 2024. All rights reserved.