How to implement an EventHandler to update controls
===

May I ask for help with the following?  

I am attempting to connect and control three pieces of household electronic equipment by computer through a GlobalCache GC-100 and iTach.  As you will see in the following code, I created a class-instance of GlobalCacheAdapter that communicates with each piece of equipment.  Although the code seems to work well in controlling each piece of equipment, I am having trouble **updating the appropriate control with the feedback from the equipment**.  The procedure "ReaderThreadProc" captures the feedback; however **I don't know how to update the associated TextBox with the feedback**.  I believe that I need to create an EventHandler to notify the TextBox of the available update; however I am uncertain as to how an EventHandler like this would be implemented.  

Any help wold be greatly appreciated.


      using System;
      using System.IO;
      using System.Net;
      using System.Net.Sockets;
      using System.Threading;
      using System.Windows.Forms;

      namespace WindowsFormsApplication1
      {
           public partial class Form1 : Form
           {

                 // Create three new instances of GlobalCacheAdaptor and connect.
                 // GC-100 (Elan) 192.168.1.70 4998  
                 // GC-100 (TuneSuite) 192.168.1.70 5000  
                 // GC iTach (Lighting) 192.168.1.71 4999
 
                 private GlobalCacheAdaptor elanGlobalCacheAdaptor;
                 private GlobalCacheAdaptor tuneSuiteGlobalCacheAdaptor;
                 private GlobalCacheAdaptor lutronGlobalCacheAdaptor;

                 public Form1()
                 {
                      InitializeComponent();
 
                      elanGlobalCacheAdaptor = new GlobalCacheAdaptor();
                      elanGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 4998);
                      tuneSuiteGlobalCacheAdaptor = new GlobalCacheAdaptor();
                      tuneSuiteGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 5000);
                      lutronGlobalCacheAdaptor = new GlobalCacheAdaptor();
                      lutronGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.71"), 4999);

                      elanTextBox.Text = elanGlobalCacheAdaptor._line;
                      tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
                      lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
               }
     
               private void btnZoneOnOff_Click(object sender, EventArgs e)    {    elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,4,1,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,800" + Environment.NewLine); }
               private void btnSourceInput1_Click(object sender, EventArgs e) {    elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,179,20,179,20,179,20,179,20,179,20,179,20,179,20,278,20,179,20,179,20,179,20,780" + Environment.NewLine); }        
               private void btnSystemOff_Click(object sender, EventArgs e)    {    elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,184,20,184,20,184,20,184,20,184,20,286,20,286,20,286,20,184,20,184,20,184,20,820" + Environment.NewLine); }
        
               private void btnLightOff_Click(object sender, EventArgs e)     {    lutronGlobalCacheAdaptor.SendMessage("sdl,14,0,0,S2\x0d"); }
               private void btnLightOn_Click(object sender, EventArgs e)      {    lutronGlobalCacheAdaptor.SendMessage("sdl,14,100,0,S2\x0d"); }

               private void btnChannel31_Click(object sender, EventArgs e)    {    tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x31\x00\x30\x21\xB8\x0D"); }
               private void btnChannel30_Click(object sender, EventArgs e)    {    tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x30\x00\x30\x21\xB8\x0D"); }
          }
    }

    public class GlobalCacheAdaptor
    {
          public Socket _multicastListener;
          public string _preferredDeviceID;
          public IPAddress _deviceAddress;
          public Socket _deviceSocket;
          public StreamWriter _deviceWriter;
          public bool _isConnected;
          public int _port;
          public IPAddress _address;
          public string _line;

          public GlobalCacheAdaptor() { }
          public static readonly GlobalCacheAdaptor Instance = new GlobalCacheAdaptor();

          public bool IsListening { get { return _multicastListener != null; } }

          public GlobalCacheAdaptor ConnectToDevice(IPAddress address, int port)
          {
                if (_deviceSocket != null) _deviceSocket.Close();
                try
                {
                      _port = port;
                      _address = address;
                      _deviceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                      _deviceSocket.Connect(new IPEndPoint(address, port)); ;
                      _deviceAddress = address;
                      var stream = new NetworkStream(_deviceSocket);
                      var reader = new StreamReader(stream);
                      var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
                      _deviceWriter = writer;
                      writer.WriteLine("getdevices");
                      var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
                      readerThread.Start(reader);
                      _isConnected = true;
                      return Instance;
               }
               catch { DisconnectFromDevice(); MessageBox.Show("ConnectToDevice Error."); throw; }
    }
         public void SendMessage(string message)
         {
               try
               {
                     var stream = new NetworkStream(_deviceSocket);
                     var reader = new StreamReader(stream);
                     var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
                     _deviceWriter = writer;
                     writer.WriteLine(message);
                     var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
                     readerThread.Start(reader);
               }
               catch { MessageBox.Show("SendMessage() Error."); }
        }
    
        public void DisconnectFromDevice()
        {
             if (_deviceSocket != null)
             {
                   try { _deviceSocket.Close(); _isConnected = false; }
                   catch { MessageBox.Show("DisconnectFromDevice Error."); }
                   _deviceSocket = null;
             }
            _deviceWriter = null;
            _deviceAddress = null;
        }
    
        private void ReaderThreadProc(object state)
        {
              var reader = (StreamReader)state;
              try
              {
                  while (true)
                  {
                     var line = reader.ReadLine();
                     if (line == null) break;
                     _line = _line + line + Environment.NewLine;
                  }
                 // Need to create EventHandler to notify the TextBoxes to update with _line
               }
               catch { MessageBox.Show("ReaderThreadProc Error."); }
        }
   }
