rodniko

i send a class variable string into a nested class by "ref" ( using a constructor).

inside this nested class i operate a thread and change the string variable value inside the thread.

from this thread i call a delegate function which points into the main (not the nested) class function, why can't i see the change in the string there why didn't the variable string changed in the thread but the class variable string itself didn't i passed it by reference!

example :

// main class
sealed public class TCPIPComm
{
private String outStr = "Out";

clientSearch = new ClientSearch(ref outStr);


// base nested class
abstract class ConnectionSearch
{
protected String MainString = "";

// constructor
protected ConnectionSearch(ref String Str)
{
MainString = Str;
}

// thread function
abstract public void RunThread();
}

// nested class
sealed class ClientSearch : ConnectionSearch
{

// constructor
public ClientSearch(ref String Str):
base(ref Str) { }

// thread
override public void RunThread()
{

String myStr = "A";
MainString = myStr; // MainString = "A" !!! MainString is outStr right

myDelegateFunc(); // calling delegate function of TCPIPComm class
}

}


void myFunc()
{

// why outStr still "out" and not "A" !!
}

}


Re: Visual C# General reference object not updated

V.Tortola

String is a inmutable reference type, this's meaning that when you reasign a string to the variable, a new object (with new reference) is created in the heap.

When you pass a string by ref, you pass the memory where the string is located, if you assign a new string value to the variable, a new object is created in the heap in another memory position, then your "by ref" variable is point to old location ;)

For this issues, use StringBuilder instead.

Also if you use multithreading consider serialize access to a variable with the "lock" statement and/or mark the variable like "volatile" in order to force to the compiler to mantaint a "always updated" variable in processor cache.

Regards.





Re: Visual C# General reference object not updated

rodniko

Thank you for the great reply!

now i understand why the main string isn't updated.

now i need to solve the problem.

My real problem is the same as the example i presented but instead of "String" type it is an "TcpClient" type ( i wrote the example with string to make it easier to understand).

for example, instead of the rows :

String myStr = "A";

MainString = myStr;

the code is :

TCPclient = listener.AcceptTcpClient(); // creates a new TcpClient object and puts it inside my  main TcpClient variable

which is the same problem exactly. inside the thread the TCPclient is not the same as the main class TcpClient because of the reason you mentioned.

but the thing is that the TcpClient doesn't have a builder like the stringbuilder , so how do i solve the problem

how do i make the main TcpClient ( or any other reference type, doesn't matter) variable point on the new TcpClient i create inside the thread





Re: Visual C# General reference object not updated

V.Tortola

"creates a new TcpClient object and puts it inside my main TcpClient variable"

Is the something than string because create a new object reference in the variable.

Put the correct code and so i can see it better :)

Regards.





Re: Visual C# General reference object not updated

rodniko

Thanks!

The point is not the TcpClient code.

the concept of the problem is for any type we choose (even Brush or any other type) because it is a reference problem.

in the string example , i created a new string inside a thread and thought that if i do "MainString = myStr;" i could make the MainString "be" myStr forever (ManString be "A" even when i call a delegate function) , but when i called the delegate function MainString is not myStr.

How do i make MainString "be" myStr ( put the pointer that represents myStr in MainString without it being gone when i get out of the thread),

Considering i can't copy the content from myStr to MainString ( in String type i can but in TcpClient type i can't because of Readonly fieds) so i need to find a way for MainString stay pointing at myStr although myStr is destroyed when the thread is gone. (pass the pointer or something).

i apologize , it is so hard for me to explain my problem.... i just want outStr to be "A" when the thread is terminated ( without copying content from myStr into MainString).





Re: Visual C# General reference object not updated

rodniko

i found a way to put myStr into outStr and that way to make outStr ="A" from inside the thread :

override public void RunThread()
{

String myStr = "A";

myDelegateFunc(myStr); // calling delegate function of TCPIPComm class
}

}


void myFunc(string tmpStr)
{
this.outStr = tmpStr // that way after myStr is terminated i still have "A" in outStr!
}

thank you for your help....





Re: Visual C# General reference object not updated

ShellShock

Do you come from a C++ background by any chance

If you look up the documentation for ref it explains your problem:

"The ref method parameter keyword on a method parameter causes a method to refer to the same variable that was passed into the method."

Note that it says "method", and not object or property.

MainString is not a pointer. Your constructor:

protected ConnectionSearch(ref String Str)
{
MainString = Str;
}

assigns the value of Str to MainString, not its address; MainString is not "pointing" at outStr, or its address. So the line

MainString = myStr; // MainString = "A" !!! MainString is outStr right

simply gives MainString another value, and does not affect outStr.

You could instead pass your TCPIPComm object into the ClientSearch constructor, and let it access the fields in the TCPIPComm object .





Re: Visual C# General reference object not updated

rodniko

Thank you shellshock, you are right , i din't notice it said method , i though reference types can in any case pass as reference.

you suggested to pass TCPIPComm into ClientSearch constructor , won't i have the same problem as passing the String variable TCPIPComm and outStr are both reference types.... won't i have the same problem again with the TCPIPComm object his field will be updated inside the thread but the real TCPIPComm object field wont... i apologize for my lack of experiance but what is the difference between passing the two into a consturctor

by the way , i am with c++ background :)





Re: Visual C# General reference object not updated

ShellShock

You have given the answer yourself: "his field will be updated inside the thread but the real TCPIPComm object field wont". So you need to pass the "real" TCPIPComm object into the ClientSearch constructor.

Here is a complete example:

using System;

namespace Test
{
public sealed class TCPIPComm
{
private string _outStr = "Out";
private ClientSearch _clientSearch;

public string OutStr
{
get { return _outStr; }
set { _outStr = value; }
}

public ClientSearch ClientSearchProperty
{
get { return _clientSearch; }
set { _clientSearch = value; }
}

public TCPIPComm()
{
_clientSearch = new ClientSearch(this);
}

public sealed class ClientSearch
{
private TCPIPComm _tcpipComm;

public ClientSearch(TCPIPComm tcpipComm)
{
_tcpipComm = tcpipComm;
}

public void RunThread()
{
_tcpipComm.OutStr = "A";
}
}

}

class ClassTest
{
[STAThread]
static void Main(string[] args)
{
TCPIPComm tcipipComm = new TCPIPComm();
Console.WriteLine("OutStr = " + tcipipComm.OutStr);
tcipipComm.ClientSearchProperty.RunThread();
Console.WriteLine("OutStr = " + tcipipComm.OutStr);
}
}
}


This will output "Out" first, and then after RunThread is called it will output "A". It is not the greatest code but it is based on your example.