特定于实例的EventHandler,提供超出类级别的数据可见性

时间:2012-07-09 21:13:44

标签: event-handling

我可以请求以下帮助吗?

我试图通过GlobalCache GC-100和iTach通过计算机连接和控制三件家用电子设备。正如您将在下面的代码中看到的,我创建了一个可以通信和控制设备的类(“GlobalCacheAdapter”),并为每个设备创建了一个类的实例。虽然每个实例似乎都能很好地进行通信和控制每个设备,但从设备* 返回的 * 反馈似乎只能在定义的类级别上看到 - “ReaderThreadProc”程序。每个设备都需要进一步处理反馈,我不确定如何在设备特定的实例级别转发此反馈。我怀疑需要实现特定于实例的EventHandler;但是我不知道如何实现这种特定于实例的EventHandler,以便完成处理并更新适当的控件。

非常感谢任何帮助。

  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;
              }
             **// Feedback from each piece of equipment is visible here.
               // Need to create EventHandler to notify the TextBoxes to update with _line**
           }
           catch { MessageBox.Show("ReaderThreadProc Error."); }
    }

}

1 个答案:

答案 0 :(得分:1)

根据我对这个问题的理解,你想做这样的事情?

enter image description here

您需要知道GlobalCacheAdapter何时更新以及更新哪个更新以更新表单上的文本框。我的问题是你 - 你真的需要知道哪些更新?

如果你在你的班级中声明一个这样的事件处理程序:

public class GlobalCacheAdaptor
{
    public event EventHandler<EventArgs> Updated;

    protected virtual void OnUpdated()
    {
        var handler = Updated;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }

    private void Foo()
    {
        // When an update is received, raise Updated event
        OnUpdated();
    }
}

然后在您的表单中订阅所有三个GlobalCacheHandler实例的更新

public Form1()
{
    elanGlobalCacheAdaptor.Updated += (s,e) => 
    {
        elanTextBox.Text = elanGlobalCacheAdaptor._line;
    }

    tuneSuiteGlobalCacheAdaptor.Updated += (s,e) => 
    {
        tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
    }

    lutronGlobalCacheAdaptor.Updated += (s,e) => 
    {
        lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
    }
}

当适当的缓存处理程序引发Updated事件时,您应该能够更新正确的文本框。

最后,您可能需要处理跨线程交互。如果是,see this article on MSDN,特别是“线程安全调用Windows窗体控件”部分