Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 9 von 9

Thema: Twincat ADS-Notifications im Thread

  1. #1
    Registriert seit
    23.07.2003
    Beiträge
    209
    Danke
    22
    Erhielt 14 Danke für 12 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hi ...

    hat jemand schon mal mit ADS in einem separaten Thread gearbeitet ? Ich starte einen Backgroundworker (oder Thread, kommt aufs gleiche raus) und geb ihm ein paar Events (AmsRouterStateChanged, AdsStateChanged, ADSIGRP_SYM_VERSION)...

    Diese Events werden aber NIE gestartet, egal was mein Ams-Router macht ... wenn ich das ganze ganz normal in einem mainform_load aufrufe funktioniert es Problemlos.

    Hat das jemand schon mal gemacht ? Ach ja C#, bevor ichs vergess...

    Die ganze Zeit hab ich in einem Timer gearbeitet, bringt natuerlich leichte Nachteile mit sich ...

    danke
    michael
    Zitieren Zitieren Twincat ADS-Notifications im Thread  

  2. #2
    Registriert seit
    24.04.2008
    Ort
    Lübeck
    Beiträge
    324
    Danke
    8
    Erhielt 63 Danke für 62 Beiträge

    Standard

    Events werden dort abgearbeitet, wo sie aufgerufen werden!

    Also werden die Events immer in dem Thread gefeuert und die angehängten Methoden in dem Thread abgearbeitet, in dem der ADS Client erzeugt wurde.

    Ich würd das spontan so machen, dass ich für jeden Event eine Methode habe, in der vom ThreadPool dann ein Thread genommen wird um darauf zu reagieren:

    Code:
    protected virtual void OnNotification (AdsNotificationEventArgs e)
    {
        ThreadPool.QuequeUserWorkItem(NotificationCallback, e);
    }
    
    public void NotificationCallback (object state)
    {
        AdsNotificationEventArgs args = (AdsNotificationEventArgs)state;
        
        // Do something...
    }
    Keine Garantie auf Richtigkeit, aber sollte schon grob passen und erklären was ich meine.

  3. #3
    nekron ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    23.07.2003
    Beiträge
    209
    Danke
    22
    Erhielt 14 Danke für 12 Beiträge

    Standard

    Moin moin Neals,

    also irgendwie bin ich anscheinend doch zu unbewandert in dem ganzen um das zu verstehen ...

    Kannst du mir eventuell mit einem konkreteren Beispiel dienen ?

    danke
    michael

  4. #4
    Registriert seit
    24.04.2008
    Ort
    Lübeck
    Beiträge
    324
    Danke
    8
    Erhielt 63 Danke für 62 Beiträge

    Standard

    Moin hört sich gut an, bin auch Norddeutscher

    Hab das Beispiel 8 aus dem InfoSys mal erweitert...

    Hier das Beispiel: http://infosys.beckhoff.com/content/...S_Sample08.exe

    Hier meine Erweiterung:

    Code:
            void AmsRouterNotificationCallback(object sender, AmsRouterNotificationEventArgs e)
            {
                // Thread aus dem ThreadPool beauftragen
                ThreadPool.QueueUserWorkItem(RouterNotificationCallback, e);
            }
    
            // Diese Funktion wird vom Thread ausgeführt
            private void RouterNotificationCallback(object e)
            {
                // Daten umwandeln
                AmsRouterNotificationEventArgs args = (AmsRouterNotificationEventArgs) e;
    
                if(args.State == AmsRouterState.Stop || args.State == AmsRouterState.Removed)
                {
                    // Verbindung abbrechen und versuchen neu aufzubauen oder so...
                }
    
                // Aus einem Thread auf Form zugreifen
                BeginInvoke((MethodInvoker) delegate
                    {
                         _routerLabelValue.Text = args.State.ToString();
                    });
            }

  5. Folgender Benutzer sagt Danke zu Neals für den nützlichen Beitrag:

    nekron (01.12.2008)

  6. #5
    nekron ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    23.07.2003
    Beiträge
    209
    Danke
    22
    Erhielt 14 Danke für 12 Beiträge

    Standard

    Moin moin Neals,

    bin zwar kein Norddeutscher, verbringe aber recht viel Zeit dort oben

    Ups - da haben wir mächtig aneinander vorbeigeredet ....

    Mein Problem ist ein ganz anderes ... Ich starte einen Thread, der eine Verbindung zum Twincat öffnet, dann ein paar Events um einen Verbindungsabbruch zu erkennen... Diese werden aber im Gegensatz zum Starten aus dem Haupt-Thread ( -> Applikation) nie aufgerufen ...

    Code:
    
    publicvoid _worker()
    {
    TcAdsClient _tcClient = newTcAdsClient();
    AdsStream dataStream = newAdsStream(30);
    while (true)
    {
    try
    {
    if (!_tcClient.IsConnected)
    {
    _tcClient.Connect(801);
    _tcClient.AddDeviceNotification(0xF008, 0x0, dataStream, AdsTransMode.OnChange, 500, 500, 0);
    _tcClient.AdsNotification += newAdsNotificationEventHandler(_tcClient_AdsNotification);
    _tcClient.AdsStateChanged += newAdsStateChangedEventHandler(_tcClient_AdsStateChanged);
    _tcClient.AmsRouterNotification += newAmsRouterNotificationEventHandler(_tcClient_AmsRouterNotification);
    }
    System.Threading.Thread.Sleep(100);
    }
    catch (AdsErrorException ex)
    {
    // ...
    }
    }
    }
    
    Das ganze jetzt ohne Retry-Time usw ... auf jeden Fall werden die Notifications nicht aufgerufen ...

    Hast Du dazu eine Idee ??

    danke
    michael

  7. #6
    Registriert seit
    24.04.2008
    Ort
    Lübeck
    Beiträge
    324
    Danke
    8
    Erhielt 63 Danke für 62 Beiträge

    Standard

    Wenn deine Funktion worker in einem Thread laufen würde, währe sie ja durchgehend dabei, neu zu connecten und den Events immer wieder die gleiche Funktion zuzuweisen. Das heißt die währe dann 10 - 20 mal oder so auf dem Event und wenn das Event gefeuert wird, wird die Funktion 10 mal ausgeführt.

    Ich würde sagen die Funktionen in der Schleiße sind fehl am Platze...

    Habs mal so gemacht:

    Code:
        public partial class Form1 : Form
        {
            private TcAdsClient tcClient;
            private AdsStream adsStream;
            private BinaryReader binRead;
            private int notificationHandle;
            Thread adsThread;
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                
                try
                {
                    adsThread = new Thread(AdsThread);
                    adsThread.Start();
                }
                catch (AdsErrorException ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    
            private void AdsThread()
            {
                tcClient = new TcAdsClient();
    
                /* connect the client to the local PLC */
                tcClient.Connect(801);
    
                adsStream = new AdsStream(2);                /* stream storing the ADS state of the PLC */
                binRead = new BinaryReader(adsStream);    /* reader to read the state data */
    
                /* register callback to react on state changes of the local AMS router */
                tcClient.AmsRouterNotification +=
                                        AmsRouterNotificationCallback;
    
    
                notificationHandle = tcClient.AddDeviceNotification(
                                            (int)AdsReservedIndexGroups.DeviceData,    /* index group of the device state*/
                                            (int)AdsReservedIndexOffsets.DeviceDataAdsState, /*index offsset of the device state */
                                            adsStream,    /* stream to store the state */
                                            AdsTransMode.OnChange,    /* transfer mode: transmit ste on change */
                                            0,    /* transmit changes immediately */
                                            0,
                                            null);
    
                /* register callback to react on state changes of the local PLC */
                tcClient.AdsNotification += OnAdsNotification;
    
                while (tcClient.IsConnected)
                {
                    Application.DoEvents();
                    Thread.Sleep(50);
                }
            }
    
            /* callback function called on state changes of the PLC */
            void OnAdsNotification(object sender, AdsNotificationEventArgs e)
            {
                if (e.NotificationHandle == notificationHandle)
                {
                    AdsState plcState = (AdsState)binRead.ReadInt16(); /* state was written to the stream */
                    BeginInvoke((MethodInvoker) delegate
                                                    {
                                                        _plcLabelValue.Text = plcState.ToString();
                                                    });
                }
            }
    
            /* callback function called on state changes of the local AMS router */
            void AmsRouterNotificationCallback(object sender, AmsRouterNotificationEventArgs e)
            {
                BeginInvoke((MethodInvoker) delegate
                                                {
                                                    _routerLabelValue.Text = e.State.ToString();
                                                });
            }
    
            private void _exitButton_Click(object sender, EventArgs e)
            {
                Close();
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                try
                {
                    adsThread.Abort();
                    tcClient.DeleteDeviceNotification(notificationHandle);
                    tcClient.Dispose();
                }
                catch (AdsErrorException ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

  8. #7
    Registriert seit
    09.03.2010
    Beiträge
    1
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    No German writing here sorry,

    I had the same problem with the onnotification. The problem resides in the property TcAdsClient.Synchronize. This one should be set to false for the notification to triggered correctly.

    Although the last sample program works great, it doesn't answer completely to the originally posted question.

  9. #8
    Registriert seit
    24.04.2008
    Ort
    Lübeck
    Beiträge
    324
    Danke
    8
    Erhielt 63 Danke für 62 Beiträge

    Standard

    My posted code was "my" best practice.

    If you set the property Synchronize to true, the client tries to fire all events in the main-thread.

    Which question is not answered yet?

  10. #9
    Registriert seit
    03.02.2009
    Beiträge
    7
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Nochmal hallo in die kompetente Runde,

    vielleicht kann ich diesen älteren Thread mit meinem Multi-Threading Problem nochmal etwas aufwärmen...
    Ich habe genau das gleiche Problem wie oben geschildert und habe alle Vorschläge durchprobiert.
    Mein Hauptunterschied ist allerdings das ich ein WPF XAML Frontend entwickle und da sieht das alles mit den Nachrichtenbearbeitungsschleifen etwas anders aus.

    Als funktionierende Alternative "polle" ich derzeit im Bulk-Verfahren. Aber die Round-Trip Zeiten sind gähnend langsam. Gefühlte 300 ms (für nur 7 bool Variablen - die wie gesagt alle in einem Rutsch übertragen werden).

    Wer hat hier einen Tipp für mich?

Ähnliche Themen

  1. Notifications vom BC9000?
    Von ThomasF im Forum CODESYS und IEC61131
    Antworten: 2
    Letzter Beitrag: 02.11.2011, 01:06
  2. [Geburtstag-Thread] plc_tippser
    Von rostiger Nagel im Forum Stammtisch
    Antworten: 23
    Letzter Beitrag: 06.02.2011, 17:09
  3. Druckversion von Thread
    Von godi im Forum Stammtisch
    Antworten: 3
    Letzter Beitrag: 03.04.2007, 15:19

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •