0

Forgive me, I'm learning C# and object-oriented programming. I am running two threads. Thread #2 calls a different class method. This method assigns an object's data value. Thread #1 unsuccessfully attempts to access the object's data value that Thread #2 assigned. The object's data value in Thread #1 is null. How do I access this object and all its assigned data values? I basically want to save the data variables from Thread #2 classes and access them from a Thread #1 class. It appears an object and it's data member values generated in a Thread #2 class are null when I leave the class and then try to access the same object in a Thread #1 class. Can I still save the instantiated object values in my example or should I declare things as static? Below is some of my code to illustrate my problem. Thank you for anyone that can recommend or illustrate how to resolve this.

// this is a main operating class that:  1) starts two threads and 2) trys to access the Thread #2 Lru_SetChanFreq class object data from Thread #1 Lru_operations class    
public class Lru_operation
{
        [STAThread]
        static void Main()
        {
            // starts a separate thread #2
            Lru_Listen LruListen1 = new Lru_Listen();
            Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
            LruListenThread.Start();

            while(!LruListenThread.IsAlive)
                ;
            Thread.Sleep(1);

            // follows the main thread #1 
            Lru_operation LruOpX = new Lru_operation();         
            LruOpX.LruOperation();                      
        }

        // this is where main thread #1 operates
        public void LruOperation()
        {       
            // create object to access object data from thread #2 Lru_SetChanFreq class 
            Lru_SetChanFreq SetChFrq = new Lru_SetChanFreq();
            try
            {
                // do stuff

                // ERROR:  SetChFrq.LruSetFrq.RxFreq2 = null and then catches an exception to go below.
                // Why is this happening if Thread #2 previously sets RxFreq2 = 405.1?
                Console.WriteLine("LruSetFrq.RxFreq2 = {0}", SetChFrq.LruSetFrq.RxFreq2);

                // do more stuff

            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "connection terminated",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

}



// this is called from thread #2.  It's object is used by thread #1   
public class Lru_SetChanFreq
{
        #region fields
        private string rxFreq2;
        private Lru_SetChanFreq mLruSetFrq;
        #endregion fields

        #region Properties
        public Lru_SetChanFreq LruSetFrq
        {
            get { return mLruSetFrq; }
            set { mLruSetFrq = value; }
        }

        public string RxFreq2
        {
            get { return rxFreq2; }
            set { rxFreq2 = value; Console.WriteLine("rxFreq2 = {0}", rxFreq2); }
        }
        #endregion Properties

        #region methods 
        public Lru_SetChanFreq()
        {
        }

        public void SetFreq()
        {   
            mLruSetFrq = new Lru_SetChanFreq();
            mLruSetFrq.RxFreq2 = "405.1";

            // I confirmed that LruSetFrq.RxFreq2 = 405.1
            Console.WriteLine("LruSetFrq.RxFreq2 = {0}", LruSetFrq.RxFreq2);

            // do stuff
        }
        #endregion methods
}


// this is starting point of thread #2   
public class Lru_Listen
    {
        #region Fields
        // stuff
        #endregion Fields

        #region Properties
        // stuff
        #endregion Properties

        #region Methods   
        public void ListenForAag()
        {
            // do stuff
            LruListenAccReq();                  
        }

        public void LruListenAccReq()
        {
            // do stuff
            LruShowRequestData(request);
        }

        public void LruShowRequestData(// stuff )
        {
            Lru_SetChanFreq SetChanFreq = new Lru_SetChanFreq();        
            SetChanFreq.SetFreq();   // calls to another class method                           
        } 
        #endregion Methods
    }
} 

2 Answers 2

3

Your 2 Threads each make an instance of Lru_SetChanFreq . The 2 instances are not related or coupled. Setting a value on one thread (SetChanFreq.SetFreq()) has no bearing on the other thread.

A few points:

  • Try to pick meaningful, readable names. Prefixes like Lru_ have a negative impact on readability.
  • Study the meaning of object-instance (vs static) first. Leave threading alone until you have a good grasp of objects and memory management.
  • In the end you probably won't want to use Threads at all, ThreadPool and Task are more efficient and convenient.
Sign up to request clarification or add additional context in comments.

2 Comments

I was thinking this.. but the code is incredibly hard to follow. Wasn't sure if I was following it correctly. +1.
Henk, thanks for your ideas. I'd like to keep this as simple as possible. There's two things my code needs to do. I need to randomly set a value to 405.1 or some other frequency. That value is actually an input from a HTTPListener. I'm acting as a server here. At the same time, I need to do periodic HTTP POSTs to another device that is acting as a server. I thought the best approach was using 2 threads. Thread #2 for acting as a server with HTTPListener and Thread #1 acting as a client with HTTP POST. As a newbie, I'm drinking from the firehydrant. Do you see a better approach?
0

Your issue is that you are initializing and accessing distinct Lru_SetChanFreq instances in your two threads. You should initialize just one, assign it to a class field, and then access the same instance from the other thread. Here is a trimmed-down version of your code that does that:

public class Lru_operation
{
    [STAThread]
    static void Main()
    {
        Lru_Listen LruListen1 = new Lru_Listen();

        // Run LruListen1 on Thread 2
        Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
        LruListenThread.Start();

        // Wait for its operation to complete
        // There is no need to wait for the thread to terminate
        LruListen1.readyEvent.WaitOne();

        // Read the Lru_SetChanFreq initialized from LruListen1,
        // and continue processing it on Thread 1
        Lru_operation LruOpX = new Lru_operation();         
        LruOpX.LruOperation(LruListen1.SetChanFreq);                      
    }

    public void LruOperation(Lru_SetChanFreq setChanFreq)
    {
        // Access the original Lru_SetChanFreq instance received as parameter
    }
}    

// this is starting point of thread #2   
public class Lru_Listen
{
    // Declare Lru_SetChanFreq as a field so as to access it externally
    internal Lru_SetChanFreq SetChanFreq;

    // Our thread synchronization event
    internal ManualResetEvent readyEvent = new ManualResetEvent(false);

    public void LruShowRequestData(// stuff )
    {
        this.SetChanFreq = new Lru_SetChanFreq();        
        SetChanFreq.SetFreq();   // calls to another class method  

        // Signal that we are ready                 
        readyEvent.Set();
    }
}

Update: I've edited my code to introduce proper thread synchronization (to replace the OP's while (LruListenThread.IsAlive) and Thread.Sleep(1)). This consists of three parts:

  1. Creating a ManualResetEvent instance that can be accessed by both threads.
  2. Calling WaitOne from Thread 1, in order to make it wait.
  3. Calling Set from Thread 2 once it completes initializing your Lru_SetChanFreq, thereby signalling to Thread 1 that it may proceed.

3 Comments

Thanks Douglas, that did it. It takes ~ 3 sec before the RxFreq2 = 405.1 on Thread #1. Anything less gives me a null. I don't yet understand why I have to wait until the operation in Thread #2 completes. The value appears to be updated in Thread #2 before that. Why can't I access the value in Thread #1 as soon as it is updated in Thread #2? Thank you again for explaining and showing your recommendation. It was extremely helpful.
@Kent: I've edited my code to introduce proper thread synchronization; see the update above.
Douglas, Thanks alot for your recommendations. I'm making that change and see how it runs. I ran into another problem. I created another forum Post to describe it. It's titled: "NullReferenceException was unhandled" error, while accessing another class object. I'm working with the same code as above. I get a different exception error trying to access class object data between classes but within the same thread. Your code recommendations have been invaluable. If your time allows, could you look at this Post? I'm having difficulty seeing where I went wrong. Thank you again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.