Pregunta

I need to read the value from PLC and display it in a form whenever the PLC Tag value changes.

There will list of tags which I need to monitor. Whenever a TAG value changes i need to call a function(different functions for each tag).

This is what I have done so far for capturing the Tag value change..

After connecting to PLC, i ll create the LIST of tags.

Read TAG values in timer.

While reading i ll check with OLDVALUES tag, if there is any change in value I ll raise an event.

This is working fine with 4 or 5 tags. When the Tag count is more, say 100, some of the Tag change events are not firing..

This is what so far I have done..

 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();
    }

I ll add the list of tags..

    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;
        }
    }

To set the initial values of the Tags.

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
    }

and the main datachange part.

     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;
        }
    }

My Queries:

1.What will happen if a event is raised while already raised event is still in progress(sub procedure is not completed)?? Is because of this reason I am missing some datachange events??

2.How to raise a raise a event automatically whenever the member of LIST value changes??

3.Any other better method to handle the timer-read-raiseevent?

¿Fue útil?

Solución

What will happen if a event is raised while already raised event is still in progress

The event won't be raised, not until your code is done executing the previous one. Clearly you'll run into trouble when the events you fire take too long, longer than 1 second. The more tags you have, or the more of them can change within one scan, the greater the odds that these events take more than 1 second and thus miss a tag change.

You'll need to de-couple the scanning from the event processing. You can do so with a worker thread that does nothing but check for tag changes in a loop. And if it sees any, put a update notification in a thread-safe queue. Another thread, like your UI thread, can empty the queue and process the notifications. The queue now acts as a buffer, providing enough storage to be able to keep up with a sudden burst of tag changes.

Otros consejos

Wouldn't it be better to create a class with old-new value in it and then a map with the tag as key to access the old-new instance?

It seems otherwise you have a lot of things floating around that need to be kept synched.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top