Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 同一应用程序的多个实例引发StackOverflow异常_C#_Wpf_Stack Overflow - Fatal编程技术网

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

C# 同一应用程序的多个实例引发StackOverflow异常,c#,wpf,stack-overflow,C#,Wpf,Stack Overflow,在我的解决方案中,我有3个主要项目(Server、Client和Special Client)。在我的测试环境中,(1)Special Client每5秒只显示一次买卖/执行订单的计数,(2)Client提交买卖订单,(3)Server处理客户提交的订单并发送回Client和Special Client。如果我按Ctrl+F5启动所有3个应用程序,让Client每10毫秒提交一个订单,所有这些应用程序都可以正常工作,在Windows任务管理器上,我观察到Client的内存使用量在115MB和32

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

如果我从
./Client/bin/Debug/…
中再启动2个
客户端
(总共3个
客户端
,1个
特殊客户端
和1个
服务器
),并让每个
客户端
每秒提交20个订单,它也可以正常工作(不确定,但可能每个
客户端的性能都会略有下降)。但是,如果我从
。/Client/bin/Debug/…
启动第四个
客户端
,并让每个客户端每秒提交20个订单,我最终会在其中一个
客户端
上获得
堆栈溢出异常

因此,简言之,一个
客户端
可以每秒提交100个订单,并从
服务器
获取所有订单,并在一台计算机上以中等复杂的用户界面上显示信息,而在一台计算机上,3个
客户端
一起可以每秒处理60个订单,但4个
客户端
一起不能每秒处理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]     
但是我的代码中没有该事件的订户!第431行引用了这一行
if(order.ExType==ExecutionType.Full)列表。删除(o);
这段代码:

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));
    }
}
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);
}
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);
}
第390行引用这一行
case Data.Action.Execute:UpdateOrderOnExecution(order);break;
和402行引用这一行
if(!e.AcceptSocket.ReceiveAsync(e))Receive(null,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));
    }
}
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);
}
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);
}
void接收(对象发送方,SocketAsyncEventArgs e)
{
if(e.bytesttransfered>0&&e.SocketError==SocketError.Success)
{
var数据=PacMan.Unpack(如缓冲区);
if(data.Type==Message.Trade)
{
e、 SetBuffer(orderBuffer,0,orderBuffer.Length);
e、 AcceptSocket.Receive(如缓冲区);
var订单=PacMan.Unpack(如缓冲区);
开关(命令动作)
{
case Data.Action.Add:AddNewOrder(订单);break;
case Data.Action.Delete:RemoveOrder(订单);break;
案例数据.Action.Modify:修改订单(订单);中断;
case Data.Action.Execute:UpdateOrderOnExecution(订单);break;
}
}
其他的
{
SetBuffer(e,数据大小);
e、 AcceptSocket.Receive(如缓冲区);
var array=e.Buffer.ToArray();
Task.Run(()=>AddNews(数组));
}
e、 SetBuffer(headerBuffer,0,headerBuffer.Length);
如果(!e.AcceptSocket.ReceiveAsync(e))接收(null,e);
}
else断开与服务器的连接(null);
}

你应该使用多线程方法我看不出你的代码有任何问题,因为你同时使用3个项目尝试使用多线程,让cpu为你处理它

Charles的“迭代”关键字给了我一个黑点子。对于任何有兴趣解决这类问题的人,这里是我的黑点子ch与堆:

1) 在
客户端
特殊客户端
中创建这三个变量:

Queue<byte[]> Orders = new Queue<byte[]>();
Timer orderProcessTimer;
bool OPTstarted;
3) 初始化构造函数中的
orderProcessTimer
,设置processing inverval并将其挂接到订单处理函数中:

orderProcessTimer = new Timer(500);
orderProcessTimer.Elapsed += ProcessOrder;
void ProcessOrder(object sender, EventArgs e)
{
    orderProcessTimer.Stop();
    var count = Orders.Count;
    if(count > 0)
    {
        for (int i = 0; i < count; i++)
        {
            var order = PacMan<AllOrderStruct>.Unpack(Orders.Dequeue());
            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;
            }
        }             
    }
    orderProcessTimer.Start();
}
4) 执行
ProcessOrder
功能中耗时的任务:

orderProcessTimer = new Timer(500);
orderProcessTimer.Elapsed += ProcessOrder;
void ProcessOrder(object sender, EventArgs e)
{
    orderProcessTimer.Stop();
    var count = Orders.Count;
    if(count > 0)
    {
        for (int i = 0; i < count; i++)
        {
            var order = PacMan<AllOrderStruct>.Unpack(Orders.Dequeue());
            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;
            }
        }             
    }
    orderProcessTimer.Start();
}
void ProcessOrder(对象发送方,事件参数e)
{
orderProcessTimer.Stop();
var count=订单数;
如果(计数>0)
{
for(int i=0;i
UpdateOrderOnExecution
处理订单和在订单视图中制作实时价格-数量图表所需的时间最多


它可以工作,但我可能不会采用这种方法,我会让运行这种类型应用程序的机器成为半堆栈机器,以提高性能。

发布生成堆栈的代码overflow@Charles,编辑了帖子,我将解决方案作为zip文件发布。有时调用堆栈窗口引用其他方法,但所有这些调用都来自
Receive
回调。@Charles,要开始测试:首先,您必须在窗口左下角的
TextBox
中指定一个名称,标题为
Client
Special Client
,第二次单击连接按钮,第三次单击启动测试按钮。要更改从
Client
自动提交订单的时间间隔,请打开名为
Client
的项目的
ClientCode.cs
,在末尾附近您将看到
#region MockTest
,您将看到
void startTest(object obj)
方法并更改此行的时间间隔
timer=new dispatchermer(){Interval=new TimeSpan(0,0,0,0,0,100)};
该方法的问题在于接收函数,即递归调用的模式
receive