Professional OPC
Development Tools

logos

Online Forums

Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.

Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.

Do not use the Contact page for technical issues.

Synchronization threads in subscription in live mapping

  • miron
  • Topic Author
  • Visitor
  • Visitor
19 Feb 2015 13:40 #2813 by miron
Ok. Thank you.

Please Log in or Create an account to join the conversation.

More
19 Feb 2015 12:23 #2811 by support
If it's working, then it is probably right :-) I haven't even expected it to be that simple.

The base implementations (in SynchronizationContext class) look like this:
        public virtual void Send(SendOrPostCallback d, Object state)
        { 
            d(state);
        }
 
        public virtual void Post(SendOrPostCallback d, Object state) 
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(d), state); 
        } 

I think that you should therefore use directly the delegate for your Post(...), because the original implementation can basically "get around" your lock by running the delegate from a thread pool thread - at any time, and without you being able to protect against it.
The following user(s) said Thank You: miron

Please Log in or Create an account to join the conversation.

  • miron
  • Topic Author
  • Visitor
  • Visitor
19 Feb 2015 10:34 #2808 by miron
Thank you for your answer.
Yes, I aware of non transactional state of OPC Server.

By using thread synchronization I would like be just sure that
when I am reading value it is not during modification by another thread.

In project I have to kinds of tags:
* one of them is only to read current state of device
these tags are using to make decision for algorithm
In moment of time I need current copy of state from devices.

Of course it is not "true" real current state.

* second kind is using for controlling device
these tags are using to make action in device,
and these tags are reading and reading directly
and method is waiting for e.g. trigger tag

Please Log in or Create an account to join the conversation.

More
19 Feb 2015 09:13 #2807 by support
Currently, improvements in this area are not in plans.

It may be difficult to understand or to cope with, but let me tell you one thing: What are you asking for seems like a reasonable requirement, but in reality, such synchronization is neither necessary nor truly helpful. That's also why providing support for it from our side is not in plans. Why?

Because there is totally no guarantee that updates that relate to one mapped object (or, to anything that you consider as a conceptually related group) are delivered together, at once.


Therefore, even if you were able to easily synchronize in the way you requested and intend to implement, you will not be guaranteed to see values that are logically consistent. The likeliness that you will see them consistent will increase, but it will not be 100%, ever.

What lies at heart of this issue has nothing to do with live mapping. It also has nothing to do with a particular OPC toolkit. It is intrinsically contained in the the OPC specs, because there is no notion of "transaction", or a requirement that "related" updates must be packed together. As such, if you are using OPC, it can only be truly resolved by extra means that live above OPC - for example, having synchronization tags that would come directly from the device, and somehow mark the beginning and end of "transactions".

I will reply separately to the next post with the SynchronizationContext implementation later.

Best regards

Please Log in or Create an account to join the conversation.

  • miron
  • Topic Author
  • Visitor
  • Visitor
18 Feb 2015 23:07 #2806 by miron
Could you check my implementation:
public class QuickOPCSyncContext : SynchronizationContext
{
        public object SynchObject {get;set;} //tu use construction with lock
 
		public QuickOPCSyncContext()
		{
		   SynchObject = new object();
		}
        public override void Post(SendOrPostCallback d, object state)
        {            
            lock(SynchObject)
			{
			    base.Post(d,state);
				//or just execute d(,state);
			}          
        }
 
        public override void Send(SendOrPostCallback d, object state)
        {            
			lock(SynchObject)
			{
			    base.Send(d,state);
				//or just execute d(,state);
			}            
        }
};
 

Remarks
1. I have used default synchronization context to derive main functionality:
QuickOPCSyncContext : SynchronizationContext
I hope that is ok.
2. set up in main thread:
var synchContext = new QuickOPCSyncContext();
SynchronizationContext.SetSynchronizationContext(new QuickOPCSyncContext());
(Quick opc thread)
3. In logic loop I would like to use property
lock(synchContext.SynchObject )
{
}
4. Should execute base method:
base.Post(d,state);
or should I execute "d" delegate
d(,state);

I have made small test and it's look that is working.
But I would like take knowledge in the origin :-).

Thank you, and qood night.
I am waiting for quick answer.

Please Log in or Create an account to join the conversation.

  • miron
  • Topic Author
  • Visitor
  • Visitor
18 Feb 2015 20:44 #2805 by miron
Thank you for your response.

Ad1. It is not nice solution, because classes become not clean. I have big project with about 600...1200 tags. And I am thinking about automatically generation PLC context classes and configuration for OPC server from Enterprise Architect. In this case I don't want to modify each property in each class.
And it would be difficult to regenerate classes from UML after providing some changes.

Unfortunately .net does not have out of the box Aspect.


Ad2. I need your little help.

===============
In my opinion this case of using QuickOPC - Live Mapping - Subscription is very obviously.
Without possibility of synchronization thread this mechanism would work as normal pooling.

Maybe do you have information when do you have plan provide this functionality?
We will start implementation of our system at customer by the and of march.

Please Log in or Create an account to join the conversation.

More
18 Feb 2015 13:03 #2804 by support
I fully understand. By "suppressing the updates", I meant controllable delaying - precisely what you suggest.

Unfortunately we currently do not support this. I can see two options to achieve the desired result:

1. Use a synchronization object with C# 'lock' statement where necessary. That would mean replacing the proposed opcSynch.Enter() and opcSynch.Exit() with the lock statement in the processing loop, and implement all property accessors (mainly, setters) so that they use a 'lock' as well. This way, the live mapping subscriptions will be blocked until you are finished with the processing (BTW, the locked part of the processing should really just make a copy of the values - the remainder can be done outside the lock).

2. All notifications go through a specified EasyDAClient.SynchronizationContext object, when provided, and the EasyDAClient for live mapping is made accessible to you via a property as well. It should be possible to write own synchronization context implementation that would do the locking.

Best regards

Please Log in or Create an account to join the conversation.

  • miron
  • Topic Author
  • Visitor
  • Visitor
17 Feb 2015 10:23 #2799 by miron
Let's take some example.

I have to have about 600 fresh value. Main loop (with work in thread) need to tests
this values to make some business logic.

I know that solution with pooling - retrieving whole 600 values,
for each execution of loop could have poor performance. Even I use "Multiple" reading.

I would like to keep "fresh" context by using Live Mapping subscription.

But in each execution loop I need little time to safety tests values.

I mean rather synchronization between thread.

If I good understand, suppress action will froze refreshing data, and after suppress whole data need to be resend (synchronize). That means for each execution of loop 600 values has to be send each time.
If yes it is not suitable solution.

Ilustration of idea:
 
void BusinessLogic()
{
    var plcContext = new MyPCContext();
 
    //Make mapping ....
    var opcSynch = QuickOPC.GetQuickOPCContext();
 
    while(true)
    {
           opcSynch.Enter()
           try
           {
               if (plcContext.Line[0].IsWorking)
               {
                  if (plcContext.Line[0].Speed > 20)
                  {
                      ...
                   } 
              }
           }
           finally
           {
             opcSynch.Exit();
           }
    }
} 
 

After execution opcSynch.Enter()

1. Quick OPC should stop updating context (object which was mapped)
2. Quick OPC should queue each update from OPC server

After execution opcSynch.Exit()

1. Should update context by data which was queued
2. Quick OPC should normally continue update context,
with out full refreshing whole data from OPC Server.

Please Log in or Create an account to join the conversation.

More
16 Feb 2015 20:38 #2794 by support
Would you basically like to suppress the incoming updates for some time, so that you can safely read out the values? - please confirm.

Please Log in or Create an account to join the conversation.

  • miron
  • Topic Author
  • Visitor
  • Visitor
16 Feb 2015 15:32 - 16 Feb 2015 15:43 #2785 by miron
By attributes I could configure my class e.g.:

public class Device
{
public int SomeValue {get;set;}
}

to use subscription SomeValue.

That means this value will be refreshing in separate thread.

What is good practice to synchronize QuickOPC thread
with another thread e.g. some loop of algorithm which in cycle testing data.

Probably using Subscribe(false) and next Subscribe(true) is bad solution
because it reloading whole subscription data after Subscribe(true).

Could you give some short example?
Last edit: 16 Feb 2015 15:43 by miron.

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.100 seconds