Version 1.6.0.0
TcHmiSrvExtNet.Core version 1.6.0.0 was released on May 16, 2022.
New features in this release
- The following events were added to allow implementing asynchronous event handlers:
- AlarmProviderListenerOnConfirmAsync
- AlarmProviderListenerOnInitialListEventsAsync
- AuthListenerOnLoginAsync
- AuthListenerOnLogoutAsync
- ConfigListenerBeforeChangeAsync
- ConfigListenerBeforeDeleteAsync
- ConfigListenerBeforeRenameAsync
- ConfigListenerOnChangeAsync
- ConfigListenerOnDeleteAsync
- ConfigListenerOnRenameAsync
- EventListenerOnChangeAsync
- EventListenerOnRemoveEventAsync
- EventListenerOnReceiveAsync
- EventListenerOnListEventsAsync
- EventLocalizationListenerOnRequestAsync
- ExportListenerBeforeExportAsync
- ExportListenerBeforeImportAsync
- HttpListenerOnHttpRequestAsync
- RequestListenerOnRequestAsync
- SessionListenerOnLoginAsync
- SessionListenerOnLogoutAsync
- SessionListenerOnCreateWebSocketAsync
- SessionListenerOnCloseWebSocketAsync
- SessionListenerOnCreateSessionAsync
- SessionListenerOnCloseSessionAsync
- ShutdownListenerOnShutdownAsync
- SubscriptionListenerOnSubscribeAsync
- SubscriptionListenerOnUnsubscribeAsync
-
Call order
Asynchronous event handlers are called before their synchronous counterparts, but awaited after calling them.
Synchronization between multiple asynchronous and synchronous event handlers has to be done in the TwinCAT HMI server extension.
Event handlers
Instead of the generic EventHandlerTEventArgs delegate type, the generic Func<object, TEventArgs, Task> delegate type is used for asynchronous event handlers, since no generic delegate type for asynchronous event handlers is currently defined in the default .NET libraries. The generic Func<object, TEventArgs, Task> delegate type is essentially equivalent to an event handler delegate type defined as follows:
public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e);
Although the generic Func<object, TEventArgs, Task> delegate type and AsyncEventHandler are equivalent because they denote a delegate of the same type, they would not be interchangeable. This is shown by the fact that a method that has one of the two delegate types as a parameter would not accept an instance of the other delegate type. Also, casting an instance of one delegate type into the other would result in an InvalidCastException because the delegate types are not related.
Why isn't AsyncEventHandler used instead of the generic generic Func<object, TEventArgs, Task> delegate type then?
AsyncEventHandler is not used because it would have to be defined somewhere in the TcHmiSrvExtNet.Core assembly. If you also want to implement asynchronous events in your assemblies, you would have to define an AsyncEventHandler there as well or add a reference to TcHmiSrvExtNet.Core.dll, both of which are probably undesirable.
The generic Func<object, TEventArgs, Task> delegate type is instead commonly available, so that no additional DLLs need to be referenced and all event handlers can be used in the same way, regardless of which assembly the corresponding event comes from.