C# WCF - Client/Server - System.OutOfMemory Except

2020-03-26 11:52发布

The Problem.

  • C# WCF Client/Server Application using Net TCP Binding (Publisher/Subscriber Pattern).
  • Client-side keeps crashing with an OutOfMemoryException.
  • When I run Task Manager along with the client, I can see the Memory Usage column increase until the application crashes.
  • Intention is for multiple instances of the client to be running on separate machines.

Scenario

  • I have a client/server application.
  • Publisher/Subscriber Design Pattern.
  • On the server-side there are 6 dictionaries that make up a cache, each containing a custom object as a value.
  • Each set of dictionary values gets updated every 5 seconds as part of a while loop.
  • At the end of the 5 second loop, the 6 dictionaries are added to a datacontract object, each as a different data member.
  • The data contract object is then sent over the wire to the client, where there are 6 more dictionaries.
  • I then loop through each data contract dictionary, and either add to or update the contents of it's client-side equivalent, depending on whether the values already exist or not.

Summary

  • 6 dictionaries server-side.
  • 6 serializable dictionaries in the data contract.
  • 6 bindable dictionaries client-side.
  • WCF using Net TCP Binding to transport data over the wire.

Specification

  • C# .Net 3.5
  • Client-side using one DevExpress form and 9 DX gridviews & tab controls.
  • Most of the custom objects containg a dictionary of "sub assets". - I have used a bindable dictionary for this property, which I imagine creates overhead when you have a few hundred objects (although I don't think using a serializable dictionary instead would make much difference, as they both contain the same code for serialization).
  • Bindings on both sides are programmatically created once at the start and contain the same settings (see below).

    NetTcpBinding netTcpBinding = new NetTcpBinding(SecurityMode.None);
    
    EndpointAddress endpointAddress = new EndpointAddress(EndpoindAddress);
    InstanceContext context = new InstanceContext(callbackinstance);
    
    netTcpBinding.MaxConnections = 5;
    netTcpBinding.MaxBufferSize = 2147483647;
    netTcpBinding.MaxBufferPoolSize = 2147483647;
    netTcpBinding.MaxReceivedMessageSize = 2147483647;
    netTcpBinding.ReceiveTimeout = TimeSpan.MaxValue;
    netTcpBinding.CloseTimeout = TimeSpan.MaxValue;
    netTcpBinding.TransferMode = TransferMode.Buffered;
    netTcpBinding.ListenBacklog = 5;
    
    DuplexChannelFactory<ISubscription> channelFactory =
       new DuplexChannelFactory<ISubscription>(
              new InstanceContext(this), 
              netTcpBinding,
              endpointAddress);
    
    proxy = channelFactory.CreateChannel();
    

My Questions

  • How can I prevent the client memory usage from growing constantly?
  • Would the memory usage on the client be significantly lower if I sent only Generic Lists of objects as opposed to serializable dictionaries?
  • Have I setup my binding configurations correctly for this kind of implementation?
  • Any other suggestions for fixing this memory problem would be greatly appreciated.

3条回答
Root(大扎)
2楼-- · 2020-03-26 12:00

Are you making sure that you only have one ServiceChannelFactory and that WCF Channels are being opened as late as possible closed as early as possible?

查看更多
太酷不给撩
3楼-- · 2020-03-26 12:06

•How can I prevent the client-interface from just growing exponentially in terms of memory usage?

Erm, its not growing exponentially, but make sure you dont have stray references, in particular look for events and lambda's that may have references to your stray objects

•Would the memory usage on the client-side be much lower if I sent only Generic Lists of objects as opposed to serializable dictionaries?

I doubt it.

•Have I setup my binding configurations correctly for this kind of implementation?

Dont see any obvious issue with them

•Any other suggestions for fixing this memory problem would be greatly appreciated.

Look up Windbg, it requires time to learn properly, but it can help you see what has references to what... it may not be what you expect

查看更多
爷、活的狠高调
4楼-- · 2020-03-26 12:20

Maxing out the MaxBufferPoolSize to 2 GB (netTcpBinding.MaxBufferPoolSize = 2147483647;) is not a wise decision unless you have the RAM to spare.

WCF will keep on accumulating buffers and you may receive an OutOfMemoryException.

There's a good explanation here.

查看更多
登录 后发表回答