2012-04-02 11 views
2

Ich muss den Wert von PLC lesen und es in einem Formular anzeigen, wann immer sich der PLC-Tag-Wert ändert.Aufrufen von Ereignissen auf PLC-Tagdatachog in C#

Es wird eine Liste von Tags geben, die ich überwachen muss. Wenn sich ein TAG-Wert ändert, muss ich eine Funktion aufrufen (unterschiedliche Funktionen für jedes Tag). Diese

ist, was ich für die Erfassung der Tag Wertänderung bisher getan ..

Nach dem Anschluss von Steuerung, ich werde die Liste der Tags erstellen.

TAG-Werte im Timer lesen.

Während des Lesens überprüfe ich mit dem OLDVALUES-Tag, wenn es irgendeine Wertänderung gibt, werde ich ein Ereignis auslösen.

Dies funktioniert gut mit 4 oder 5 Tags. Wenn der Tag zu veröffentlichen ist, sagen wir 100, sind nicht einige der Tag Änderungsereignisse Brennen ..

Dies ist, was bisher habe ich getan ..

public delegate void DataChangedEventHandler(string TagName, string NewValue); 
    private Timer tmr = new Timer(); 

    public event DataChangedEventHandler OnDataChanged; 
    private void StartTimer(DataTable dt) 
    { 
     AddTagList(dt); 
     SetInitialVales(); 
     tmr.Tick += timerticks; 
     tmr.Interval = 250; 
     tmr.Enabled = true; 
     tmr.Start(); 
    } 
    private void StopTimer() 
    { 
     tmr.Enabled = false; 
     tmr.Stop(); 
    } 

ich die Liste der Tags hinzufügen werde. .

private List<string> TagValues = new List<string>(); 
    private List<string> oldValues = new List<string>(); 
    private List<string> newValues = new List<string>(); 
    private void AddTagList(DataTable dt) 
    { 
     int ILoop = 0; 

     foreach (DataRow row in dt.Rows) 
     { 
      TagValues.Add((string)row["Path"]); 
      ILoop = ILoop + 1; 
     } 
    } 

Um die Anfangswerte der Tags festzulegen.

private void SetInitialVales() 
    { 
     int iLoop = 0; 
     foreach (string vals in TagValues) 
     { 
      var rd = ReadTag(vals); 
      oldValues.Add(rd.ToString()); 
      newValues.Add(rd.ToString()); 
      iLoop = iLoop + 1; 
     } 
     //newValues = oldValues 
    } 

und der Hauptteil Datenaustausch.

 private void timerticks(object sender, EventArgs eventArgs) 
    { 
     int iLoop = 0; 
     foreach (string vals in TagValues) 
     { 
      oldValues[iLoop] = ReadTag(vals).ToString(); 
      if (oldValues[iLoop] != newValues[iLoop]) 
      { 
       newValues[iLoop] = oldValues[iLoop]; 
       if (OnDataChanged != null) 
       { 
        OnDataChanged(vals, newValues[iLoop]); 
       } 
      } 
      iLoop = iLoop + 1; 
     } 
    } 

Meine Anfragen:

1.What passieren wird, wenn ein Ereignis ausgelöst wird, während bereits angehoben Ereignis noch im Gange ist (Sub-Prozedur nicht abgeschlossen ist) ?? Aus diesem Grund fehlen mir einige Datenänderungsereignisse ??

2.Wie erhöhe ich ein Ereignis automatisch, wenn sich das Mitglied des LIST-Wertes ändert ??

3. Gibt es noch eine andere bessere Methode, um das Timer-Read-Raise-Ereignis zu behandeln?

+1

Stellen Sie sich vor, was passiert, wenn ein Tag in weniger als 250 Millisekunden ein- und ausgeschaltet wird. –

+0

Danke. dass wir uns darum gekümmert haben. Keines der Tags verhält sich so. – Olivarsham

+1

Das ist ungewöhnlich. Wie verhalten sie sich? Sind sie für eine Sekunde garantiert? Was passiert, wenn Ihr Code mehr als eine Sekunde braucht, wenn Sie viele Tags haben? Oder ist es verriegelt, so dass der Tag immer aktiviert ist, egal wie lange der Code dauert? –

Antwort

2

Was passiert, wenn ein Ereignis ausgelöst wird, während bereits angehoben Ereignis noch im Gang ist

Die Veranstaltung wird nicht angehoben werden, erst Code ausgeführt wird getan, um die vorherigen. Natürlich werden Sie in Schwierigkeiten geraten, wenn die Ereignisse, die Sie auslösen, zu lange dauern, länger als 1 Sekunde. Je mehr Tags Sie haben oder je mehr Sie sich innerhalb eines Scans ändern können, desto größer ist die Wahrscheinlichkeit, dass diese Ereignisse länger als 1 Sekunde dauern und somit einen Tagwechsel verpassen.

Sie müssen den Scanvorgang von der Ereignisverarbeitung trennen. Sie können dies mit einem Worker-Thread tun, der nur nach Tag-Änderungen in einer Schleife sucht. Und wenn es eines sieht, legen Sie eine Update-Benachrichtigung in eine thread-sichere Warteschlange. Ein anderer Thread, wie Ihr UI-Thread, kann die Warteschlange leeren und die Benachrichtigungen verarbeiten.Die Warteschlange fungiert nun als Puffer und bietet genügend Speicherplatz, um mit einem plötzlichen Ausbruch von Tag-Änderungen Schritt halten zu können.

1

Wäre es nicht besser, eine Klasse mit alt-neuem Wert darin zu erstellen und dann eine Karte mit dem Tag als Schlüssel, um auf die alt-neue Instanz zuzugreifen?

Es scheint, als hätten Sie sonst eine Menge Dinge, die herumgeschleudert werden müssen, die synchron gehalten werden müssen.

+0

Kannst du bitte einige Proben posten oder ausarbeiten ?? Sie meinen, eine separate Klasse für jedes Tag mit ihren Werten als Eigenschaften zu erstellen? – Olivarsham