I’ve created an abstract class which implements a method that runs another abstract method on a seperate thread, like this:
public abstract class ATest
{
Thread t;
protected String status;
public void Start()
{
ThreadStart ts = new ThreadStart(PerformTest);
t = new Thread(ts);
t.Start();
}
public ATest(String status)
{
this.status=status;
}
public abstract void PerformTest();
}
The idea is that classes deriving from ATest only implements the PerformTest method. Thus, any client can just call the Start() method to start the operations within PerformTest() on its own thread. An class deriving from ATest might look like:
class ConcreteTest:ATest
{
public ConcreteTest(String status):base(status)
{
}
public override void PerformTest()
{
// Do some things...
// And some more...
status = "changed";
}
}
When creating a ConcreteTest object I want to pass in some object (in the example a String). When PerformTest() runs on its seperate thread the state of this object is to be changed dependent on the outcome of the operations in PerformTest(). An example using the above classes:
class Program
{
static void Main(string[] args)
{
String isPassed = "original";
ATest test = new ConcreteTest(isPassed);
test.Start();
Console.WriteLine(isPassed); // Prints out "original"
}
}
So I set isPassed to “originial” and passes it to ConcreteTest, which on a separate thread changes to value to “changed”. So when i print out isPassed I hoped for the value to be set to “changed”, but it turns out it isn’t. I guess this have something to do with the value being changed on another thread that the one it was originally created on. Can anyone please explain to me why I get this behavior, and perhaps what I could do to achieve the functionality I’m looking for (that is to change isPassed on the separate thread so that when the thread is done, the Console would print out “changed”?
Strings are immutable.
When you write
status = "changed", you aren’t changing any existing string object.Instead, your are changing the
statusfield to refer to an entirely differentStringinstance.The
statusfield has nothing to do with theisPassedvariable in yourMainmethod. When you writenew ConcreteTest(isPassed), you are passing the value of theisPassedvariable to the constructor.The parameter has nothing to do with the variable that you passed to it, except that for now, they happen to refer to the same object. The same is true of your
statusfield.The simplest way to do this is to define a holder type, like this:
If you want to, you can add an implicit cast and a constructor.
You can also do this by exposing the
Statusproperty in your base class and writingtest.StatusinMain.You also have a less obvious problem.
There is nothing in your code that forces it to wait for the other thread to finish, so your
Console.WriteLinemight run before the field is assigned by the other thread.