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.

Newbie question: Best method for item identification from callback

More
18 Jan 2016 12:14 #3777 by support
Oh, I see. Thanks for clarification.

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

More
18 Jan 2016 11:35 #3776 by Hanssing

support wrote: Thought there had to be a simpler way.


Sorry, not clear what I wrote... What I meant, was that the method I originally used (Ie identifying the Item-Id), seemed too cumbersome, and that there had to be a better way - which there is; using State-object for it's intended purpose as object/reference-pointer to the Item being updated.

Regards
Hanssing

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

More
18 Jan 2016 11:32 #3775 by support
I welcome your recommendation about improving the examples in this respect.

And, I am really curious, re

Thought there had to be a simpler way.

How would you like to see this done in a simpler or better way?

Many thanks in advance

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

More
18 Jan 2016 10:34 - 18 Jan 2016 11:10 #3774 by Hanssing

support wrote: Use the state instead of handles to identify subscribed entities

Ahh, so thats what 'State' is for :huh:
It's a generic reference-pointer.
So simple to just box an array-indexer into that, and unbox in the callback.

Thanks! Thought there had to be a simplere way.

PS: I recommend implementing this in one one of the subscribe-examples, all I found was using NULL-references to State-object (5.31).


Hanssing
Last edit: 18 Jan 2016 11:10 by Hanssing.

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

More
15 Jan 2016 15:41 #3766 by support
To your second question: The synchronization is basically "up to you", as a developer, but we provide some hints and helpers. Also, when using the State object instead of the handles, in some cases the synchronization code becomes much easier or simply goes away. Here is a relevant part of the documentation:

Multithreading and Synchronization

The EasyDAClient, EasyAEClient and EasyUAClient objects and all their related helper objects are thread-safe.

In QuickOPC.NET and QuickOPC-UA, if you are hooking to the event notifications provided by the EasyDAClient , EasyAEClient or EasyUAClient component, or processing these notifications in your callback methods, make sure that you understand how the component generates these events and what threading issues it may involve. This is how it works:

The EasyDAClient, EasyAEClient or EasyUAClient object has a SynchronizationContext property. This property can either be set to a null reference, or to an instance of SystemThreading.SynchronizationContext class. When the SynchronizationContext is set to a null reference, EasyDAClient, EasyAEClient or EasyUAClient calls any event handlers or callback methods on its own internal thread, which is possibly different from any threads that you have in your application. When the SynchronizationContext is set to a concrete instance, the synchronization model implemented by this object is used. The EasyDAClient, EasyAEClient or EasyUAClient then typically uses the Post method of this synchronization context to invoke event handlers in your application.

When the EasyDAClient, EasyAEClient or EasyUAClient object is initially created, it attempts to obtain the synchronization context from the current thread (the thread that is executing the constructor). As a result, if the thread constructing the EasyDAClient, EasyAEClient or EasyUAClient object has a synchronization context associated with it, it will become the value of the SynchronizationContext property. Otherwise, the SynchronizationContext property will be set to a null reference. This way, the synchronization context propagates from the constructing thread.

Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are also possible, such as race conditions and deadlocks. It is important to make sure that access to your controls is performed in a thread-safe way. Thanks to the mechanism described above, this is done automatically for you, provided that the constructor of the EasyDAClient, EasyAEClient or EasyUAClient object is called on the form’s main thread, as is the case if you place the EasyDAClient , EasyAEClient or EasyUAClient component on the form’s design surface in Visual Studio. This works because by default, Windows Forms sets the synchronization context of the form’s main thread to a properly initialized instance of System.Windows.Forms.WindowsFormsSynchronizationContext object.

Similarly, Windows Presentation Foundation (WPF) applications use System.Windows.Threading.DispatcherSynchronizationContext to achieve the same thing.

If your application is not based on the above frameworks, or is using them in an unusual way, you may have to take care of the synchronization issues related to event notification yourself, either by directly coding the synchronization mechanism, or by implementing and using a class derived from SystemThreading.SynchronizationContext.

Best regards

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

More
15 Jan 2016 15:38 #3765 by support
Hello, thank you for your interest in our products.

Here is a part of the documentation (from the Concepts document) that answers your first question. I will reply to the second question separately later.

Use the state instead of handles to identify subscribed entities

The handles returned from any EasyXXClient.SubscribeXXXX methods are only meant for use as input arguments to other methods that manipulate the existing subscriptions – such as EasyXXClient.ChangeXXXX or EasyXXClient.UnsubscribeXXXX.
If you need to identify the subscribed entities inside event handlers, use the ‘state’ argument that can be passed to EasyXXClient.SubscribeXXXX methods (or a State property on XXXXArguments objects). You can pass any type of object in the state, as it is of type System.Object (and then cast the System.Object back to the original type in the event handler).
Why shouldn’t the handles be used? There are multiple reasons for that:

1. The SubscribeXXXX methods are asynchronous. There is no guaranteed relation between the moment the SubscribeXXXX method returns, and the moment when events start flowing into your event handler. The events can start flowing before the methods returns. Or, they can start flowing after the method returns, but before you get a chance to process the returned handles, and store them somewhere where the event handler can access them.

2. Similarly, UnsubscribeXXXX methods are asynchronous as well, and therefore you cannot know precisely when any event handle became invalid. You may (temporarily) receive events for a previously returned handles, even after the UnsubscribeXXXX method finishes.

4. You will need to set up and properly maintain an additional data structure – something that keeps a correspondence between the handles returned (whose values you do not know in advance), and your application data that relate to these handles. Typically, this data structure is a dictionary. Maintaining and accessing this additional data structure means extra code, and inefficient access (application data must be looked up by handle from inside the event handler).

3. Using the handles returned from SubscribeXXXX in an event handler requires coordination of the access to a data structure where the handles are stored – i.e. an inter-thread synchronization. This leads to complicated and often buggy code, with risk of deadlocks or invalid data being accessed.
All these disadvantages can simply be overcome by passing the application data needed into the SubscribeXXXX method as a state object, and then casting the State to the appropriate type and using directly inside the event handler.


The value of State that you pass in is then available under .Arguments.State from inside the event handler.

Best regards

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

More
15 Jan 2016 13:47 #3764 by Hanssing
Newbie questions here, as I dont think the examples or manuals are very good on subsription toppics.

Using C# + QiuckOPC 5.31:
  • Which items in callback?
  • I have subscription up and running, and I get the INT-array during subscribemultipleitems. But the handles are obsolete?
    Which method is best for identifying the object generation the callback, if not comparing INT-handles?
    Right now I build a string of Item-id, server-id, machine-id etc. And do string-compare, but that seems waste-full, CPU-wise.

  • Multithreading Callbacks
  • How to make a simple callback update thread-safe?
    Is it to do semaphore-blocking of access by the callback to data-areas, or are the more "correct" ways of doing this?

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

Moderators: support
Time to create page: 0.057 seconds