Laden...

Klassenübertragung im Netzwerk die Xte

Erstellt von lexy vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.740 Views
L
lexy Themenstarter:in
10 Beiträge seit 2010
vor 11 Jahren
Klassenübertragung im Netzwerk die Xte

Hallo Forum,

Ich arbeite seit ein paar Tagen an einem kleinem Programm, welches Daten von einem RS232 Port empfängt, dekodiert und dann diese in eine selbstgeschriebene Klasse schreibt.

Die Daten aus der Klasse möchte ich nun auf anfrage eines "Clients" über das Netzwerk versenden.

Das problem ist nun, dass ich den Thread in dem der Netzwerkteil läuft nicht beendet bekomme.

Den Code habe ich der Übersichtlichkeit halber bei pastebin eingefügt:


using ASAC_V;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Vestas;
using System.Runtime.Serialization;


namespace VCTS
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    /// 
    

    
    public partial class MainWindow : Window
    {
        public bool settings_changed = false;
        public SerialPort myPort = new SerialPort();
        public VestasDataValues myValues = new VestasDataValues();
        public byte error_counter = 0;
        static TClient myTClient = new TClient();
        public bool appstartup = true;
        Properties.Settings mySettings = new Properties.Settings();
        
        Thread my_Thread = new Thread(new ThreadStart(myTClient.TCPThread));

        public MainWindow()
        {
            
            InitializeComponent();
            startup();
        }

        private void startup()
        {
            
            myPort.DataReceived += myPort_DataReceived;
            //TClient myTClient = new TClient();  
            setCBoxes();
            
            if (mySettings.startup == true)
            {
                MessageBox.Show("Bitte legen Sie zum ersten Start der Anwendung die Einstellungen des Com Ports fest.", "Einstellungen", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                myPort = mySettings.mySerialPort;
                cbComPort.Text = myPort.PortName;
                cbBaudRate.Text = myPort.BaudRate.ToString();
            }

        }

        private void setCBoxes()
        {
            string[] ports = SerialPort.GetPortNames();

            foreach (string i in ports)
            {
                cbComPort.Items.Add(i);
            }

            for (int i = 5; i < 9; i++)
            {
                cbDatenBits.Items.Add(i);
            }

            for (int i = 1200; i < 10800; i += 1200)
            {
                cbBaudRate.Items.Add(i);
            }

            cbParity.Items.Add(Parity.Even);
            cbParity.Items.Add(Parity.Mark);
            cbParity.Items.Add(Parity.None);
            cbParity.Items.Add(Parity.Odd);
            cbParity.Items.Add(Parity.Space);

            cbStopbits.Items.Add(StopBits.None);
            cbStopbits.Items.Add(StopBits.One);
            cbStopbits.Items.Add(StopBits.OnePointFive);
            cbStopbits.Items.Add(StopBits.Two);
        }

        private void myPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            tMessage.Text = myPort.ReadExisting();
            if (VestasFunctions.check_checksum(myPort.ReadExisting()))
            {
                myValues = VestasFunctions.cp_message_data_into_data_value_list(VestasFunctions.decode_vce_message(myPort.ReadExisting()));

                lock (this)
                {
                    TClient.EXValue = myValues;
                }
            }
            else
            {
                tMessage.Text = "Fehler in der VCE-Nachricht ! ";
                error_counter++;
            }
            if (error_counter == 10)
            {
                bStop_Click(this, new RoutedEventArgs());
                MessageBox.Show("Zu viele Übertragungsfehler ! Bitte überprüfen sie dir Verbindung", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void bStart_Click(object sender, RoutedEventArgs e)
        {
            if (settings_changed == true)
            {

                if (my_Thread.IsAlive == false)
                {
                    my_Thread.Start();
                }
                else
                {
                    MessageBox.Show("Fehler in der Anwenung bitte neu starten!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Stop);
                    return;
                }
                cbComPort.IsEnabled = false;
                cbBaudRate.IsEnabled = false;
                cbDatenBits.IsEnabled = false;
                cbParity.IsEnabled = false;
                cbStopbits.IsEnabled = false;
                
            }
            else
            {
                MessageBox.Show("Die Einstellungen wurden nicht festgelegt", "Einstellungen", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }

        private void bStop_Click(object sender, RoutedEventArgs e)
        {
            cbComPort.IsEnabled = true;
            cbBaudRate.IsEnabled = true;
            cbDatenBits.IsEnabled = true;
            cbParity.IsEnabled = true;
            cbStopbits.IsEnabled = true;
            TClient.tcpthread_run = false;

            MessageBox.Show(my_Thread.ThreadState.ToString());

            while (my_Thread.ThreadState != ThreadState.Aborted)
            {
                tMessage.Text = "Warte auf beendigung des Netzwerkthreads";
            }
        }

        #region Comboboxen auswahl verabeiten

        private void cbComPort_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            settings_changed = true;
            myPort.PortName = (string)cbComPort.SelectedItem; ;
        }

        private void cbBaudRate_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            settings_changed = true;
            myPort.BaudRate = Convert.ToInt16(cbBaudRate.SelectedItem);
        }

        private void cbDatenBits_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            settings_changed = true;
            myPort.DataBits = Convert.ToInt16(cbDatenBits.SelectedItem);
        }
        
        private void cbParity_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            myPort.Parity = (Parity)cbParity.SelectedItem;
        }

        private void cbStopbits_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            myPort.StopBits = (StopBits)cbStopbits.SelectedItem;
        }

        #endregion

        private void update_DataValuesMethod()
        {
        }

        private void vct_closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            
            mySettings.mySerialPort.BaudRate = myPort.BaudRate;
            mySettings.mySerialPort.DataBits = myPort.DataBits;
            mySettings.mySerialPort.Parity = myPort.Parity;
            mySettings.mySerialPort.StopBits = myPort.StopBits;
            mySettings.mySerialPort.PortName = myPort.PortName;
            mySettings.Save();
        }

 


    }

    public class TClient
    {
        public static VestasDataValues EXValue = new VestasDataValues(); // Austauschvariable für die kommunikation zwischen den Threads
        public static bool tcpthread_run = true;



        public void TCPThread()
        {
          TcpListener myListener = new TcpListener(IPAddress.Parse("127.0.0.1"),6000);

          myListener.Start();

          TcpClient client = myListener.AcceptTcpClient();
          
          NetworkStream nStream = client.GetStream();


          BinaryReader bReader = new BinaryReader(nStream, Encoding.ASCII);
          BinaryWriter bWriter = new BinaryWriter(nStream, Encoding.ASCII);



          while (tcpthread_run == true)
          {
              if (bReader.ReadString() == ClientMessages.RequestConnect)
              {
                  bWriter.Write(ServerMessages.AcknowledgeOK);

                  while (bReader.ReadString() == ClientMessages.ReqData)
                  {
                      if (EXValue != null)
                      {
                          lock (this)
                          {
                              bWriter.Write(GetSerializedObject(EXValue));
                          }
                      }
                      else
                      {

                          bWriter.Write(ServerMessages.NotAvailable);
                      }
                  }

              }
          }
          
        }

        public static byte[] GetSerializedObject(object obj)
        {
            System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                formatter.Serialize(ms, obj);
                return ms.ToArray();
            }
        }
    }

}

Ich denke es ist einfach ein ganz simples Problem und ich seh den Wald vor lauter Bäumen einfach nicht ... 😦

Mit freundlichen grüßen lexy.

Hinweis von gfoidl vor 11 Jahren

[Hinweis] Wie poste ich richtig? Punkt 6.1 gilt analog, daher den Code direkt in den Beitrag, allerdings unter Beachtung von Punkt 4.c, 4.1 und 5.

C
2.121 Beiträge seit 2010
vor 11 Jahren

Guck dir im Debugger an wo der Thread hängt. Das ist schneller und besser als ein paar Vermutungen von jemandem, der versucht deinen Code in der Theorie zu verstehen und dann eine Antwort gibt die stimmen kann, oder auch nicht 😉

A
764 Beiträge seit 2007
vor 11 Jahren

Die Daten aus der Klasse möchte ich nun auf anfrage eines "Clients" über das Netzwerk versenden.

Dafür eignet sich unter umständen auch das Zyan Communication Framework.

L
lexy Themenstarter:in
10 Beiträge seit 2010
vor 11 Jahren

Danke =)

Ich habe das jetzt mal mit dem ZyanFramework ausprobiert bzw. mir mal angeschaut.
Dies scheint für meine Zwecke wirklich einfacher zu sein.
Ich habe auch bereits versucht das Framework in das projekt einzubauen, bekomme allerdings eine ApplicationException 😕

Fehlermeldung:
Für Schnittstelle 'ConsoleApplication2.IEchoComponent' ist auf dem Server 'http://localhost:8080/EchoExample' keine Komponente registriert.

Codeausschnitt aus Server Teil:


        private void Communication()
        {
            
            HttpCustomServerProtocolSetup protocolSetup = new HttpCustomServerProtocolSetup(8080, new NullAuthenticationProvider(), true);
            ZyanComponentHost myHost = new ZyanComponentHost("EchoExample",protocolSetup);
            VestasComponent myCP = new VestasComponent();

            myHost.RegisterComponent<IVestasComponent, VestasComponent>(ActivationType.SingleCall);
            myHost.ClientLoggedOn += myHost_ClientLoggedOn;
        }

        void myHost_ClientLoggedOn(object sender, LoginEventArgs e)
        {
            MessageBox.Show("Client LoggedOn");
        }

    }
  
        public interface IVestasComponent
        {
            VestasDataValues getValue();
        }
    
        public class VestasComponent : IVestasComponent
        {
            private VestasDataValues myValue;
            public VestasDataValues getValue()
            {
                return myValue;
            }
        }

Codeausschnitt aus Client Teil:


namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpCustomClientProtocolSetup protocolSetup = new HttpCustomClientProtocolSetup(true);
            ZyanConnection connection = new ZyanConnection("http://localhost:8080/EchoExample", protocolSetup);

            IVestasComponent proxy = connection.CreateProxy<IVestasComponent>();

            Console.WriteLine(proxy.getValue().Vestas_DataValues_RCS.ToString());
        }
    }

    public interface IVestasComponent
    {
        VestasDataValues getValue();
    }

    public class VestasComponent : IVestasComponent
    {
        private VestasDataValues myValue;
        public VestasDataValues getValue()
        {
            return myValue;
        }
    }

}

Ich habe dies so aus der Dokumentation übernommen und nur die Namen und Typen geändert.

Edit: Habe vergessen 2 Namen zu ändern ... Ändert aber nichts an dem Problem

A
764 Beiträge seit 2007
vor 11 Jahren

hallo lexy,

es kann sein, dass das Programm (bzw VS) als Administrator gestartet werden muss. Da gibts dann später auch ne Lösung ohne Administrator, bzw. dass es nach Adminrechten fragt.

Gruß, Alf

L
lexy Themenstarter:in
10 Beiträge seit 2010
vor 11 Jahren

Also an der fehlenden Administratorberchnung liegt es nicht.
Ich habe auch schon die verschiedenen Protokolle durchprobiert was auch nicht funktioniert hat.

3.728 Beiträge seit 2005
vor 11 Jahren
Komponente mit Zyan bereitstellen

Hallo lexi,

die Schnittstelle IVestasComponent hast Du doppelt. Einmal im Server und einmal im Client. Auch wenn sie beide gleich heißen, sind es zwei verschiedene Typen für die .NET Laufzeitumgebung.

Damit es funktioniert, musst Du die Schnittstelle in eine separate Assembly (also auch separates Visual Studio Projekt vom Typ Klassenbibliothek) auslagern. Diese Schnittstellen-Assembly musst Du ja im Server und im Client als Verweis einbinden. Deshalb wird eine solche Assembly auch Shared Assembly (also gemeinsame Assembly) genannt. Client und Server kommunizieren über eine gemeinsame Schnittstelle (nämlich IVestasComponent). Damit das funktioniert muss es auch wirklich die selbe Schnittstelle sein.

Du kannst das auch noch mal hier nachlesen: http://zyan.codeplex.com/wikipage?title=Erste%20Schritte&referringTitle=Deutsche%20Dokumentation

Gruß
Rainbird

L
lexy Themenstarter:in
10 Beiträge seit 2010
vor 11 Jahren

Danke jetzt funktioniert es =)

Tut mir leid für die späte Antwort leider hat mein MOdem gestreikt.... 😕

Mfg lexy