在我的解决方案中,我有3个主要项目(Server
,Client
和Special Client
)。在我的测试环境中,(1)Special Client
仅每5秒显示一次购买/出售/已执行订单的数量,(2)Client
提交购买/出售订单,(3)Server
处理客户提交的订单,发送回Client
和Special 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);
}
您应该使用多线程方法,因为您正在同时使用3个项目,请尝试使用多线程并让CPU为您处理它,因为我没有在代码中看到任何问题,所以>
[Charles