c# pass object by reference, wrapped TCP socket

jetbet
jetbet used Ask the Experts™
on
I have an application that has a primary and secondary data source that it connects to. I create and update an object when the primary server  crashes so that all requests will be done on the secondary until it comes back up.
public class RequestStream
    {
        private TcpClient socket;
        private NetworkStream stream;
        private String address;
        private String port;

        public RequestStream(String aAddress, String aPort)
        {
            address = aAddress;
            port = aPort;
            try
            {
                socket = new TcpClient();
                socket.Connect(address, int.Parse(port));
                stream = socket.GetStream();
            }
            catch (Exception ex)
            {
               //
            }
        }

Open in new window

I have a separate thread that "heartbeats" the servers to check their status. When I need to change servers I trigger the following code situated on the DataStore object.
public void resetAllThreads()
        {
            try
            {
                lock (_locker)
                {
                    requestStream = new RequestStream(jeqiReference.GetAddress(), jeqiReference.GetPort());
                }
            }
            catch (Exception ex)
            {
               //
            }
        }

Open in new window

A breakpoint shows this is working correctly.

I pass a copy of the RequestStream to the constructor of an object called Raceday
requestStream = new RequestStream(jeqiReference.GetAddress(), jeqiReference.GetPort());

raceDay = new RaceDay(jeqiReference, ref requestStream);

Open in new window


The trouble is that the DataStore object correctly uses the new server but the Raceday object does not. On the Raceday object the adress stays the same but the stream is null. If I restart the Server and the object is updated again, the stream is now initiated again and works as before.

The Request stream object is passed through the raceday object to another set of objects, each of which again passes this through in other constructors.

How can I ensure the RequestStream in all the objects is the same object so this will work as intended?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Miguel OzSenior Software Engineer
Top Expert 2009

Commented:
Do not use parameter by reference. In your class ensure that Request stream object is passed by value:
public RaceDay (Whatever jeqiReference, RequestStream requestStream)
{//your code goes here}

Open in new window


When you are passing the object by value,  the value is a reference for reference types - a way of getting to the object (a pointer to memory location). The RaceDay class will not be able to change the stream object but only its public properties or whatever state is changed by public methods.

Author

Commented:
I originally did not use the ref keyword and experienced the same issue.

I have removed it again but the problem remains.
Top Expert 2016

Commented:
On the Raceday object the adress stays the same but the stream is null.
since you created a new RequestStream and a new Raceday object, the old RequestStream and old Raceday object are no longer valid and are subject of the garbage collector (gc). that means the Raceday objetc you were looking for is no longer the one which should be alive but needs to be replaced by the new one.

the gc might be able to do this granted that there are no references to the old objects which prevent the old objects to be released and granted that you provided destructors which properly release and close all their open resources.

with other words: the statement
raceDay = new RaceDay(jeqiReference, ref requestStream);

Open in new window

should release and clear old raceDay object.

Sara
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Author

Commented:
Sorry I did not explain well enough.

The DataStore contains a Raceday and these are not destroyed until the Application closes.

The issue is with the RequestStream object that is used by The DataCenter, Raceday, Meeting, etc. type objects.

This is updated as necessary when there are issues with one of the servers. The problem is that there should be just one and each object needs a reference to it.

Each object that contains a reference can use it to update its own state via new information contained in an XML request/response via TCP
Top Expert 2016
Commented:
The problem is that there should be just one and each object needs a reference to it.
with
requestStream = new RequestStream(jeqiReference.GetAddress(), jeqiReference.GetPort());

Open in new window

you create a new object and the old one is not deleted if there are still references to it. same applies for the Raceday object. if you want to have  singletons for those objects, you have to create them only once (with new) and then update the existing objects rather than to creating new ones. for example you could create temporarily new objects and 'assign' the new objects to the singletons.

Sara

Author

Commented:
That was it.
I had assumed that the link to the piece of memory where the RequestStream was stored would remain valid for the references.
Thanks for the help

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial