1

次のことについて助けを求めてもいいですか?

GlobalCache GC-100とiTachを介して、3台の家庭用電子機器をコンピューターで接続および制御しようとしています。次のコードでわかるように、機器と通信および制御できるクラス( "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."); }
    }

}

4

1 に答える 1

1

私の質問の理解から、あなたはこのようなことをしたいですか?

ここに画像の説明を入力してください

フォームのテキストボックスを更新するには、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();
    }
}

次に、フォームで、3つのGlobalCacheHandlerインスタンスすべてのUpdatedをサブスクライブします。

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イベントを発生させたときに、正しいテキストボックスを更新できるはずです。

最後に、スレッド間の相互作用を処理する必要がある場合があります。その場合は、MSDNのこの記事、特に「Windowsフォームコントロールへのスレッドセーフな呼び出し」の部分を参照してください。

于 2012-07-11T11:07:21.623 に答える