MessageSubscriberAttribute

You don't need to explicitly subscribe the MessageChannel.MessageArrived event. Instead you mark the subscribing method with the MessageSubscriberAttribute. All methods marked with the MessageSubscriberAttribute are added to the subscriber list of the particular message channel during the ComponentContainer.Add() method.

        [MessageSubscriber("MyMessageChannelName")]
        private void handleLoginRequestMessage(LoginRequestMessage m) {...}
After a new message arrives the ComponentContainer searches its invocation list for methods with a matching parameter type. In the example above it would be LoginRequestMessage or its ancestors. Matching methods are invoked.

Using UI Thread

Sometimes you need to invoke a method on the UI thread. Instead using Control.Invoke() or Control.BeginInvoke you define the synchronization mode in the declarative way.

    public enum UIThreadSynchronizationMode
    {
        /// <summary>
        /// No synchronization occures.
        /// The method is invoked in the message channel internal thread.
        /// </summary>
        IgnoreSynchronization,
        ///<summary>
        /// Method is invoked in the UI thread and the message channel is blocked until the method returns.
        /// Not recommended until the UI must change the message content.
        /// However changing the message content should be made in a component
        /// and not in an UI control.
        ///</summary>
        SendSynchronousInUIThread,
        ///<summary>
        /// Method is invoked in the UI thread without blocking the message channel.
        /// This mode is recommended for UI actualizing.
        ///</summary>
        PostAsynchronousInUIThread
    }
The MessageSubscriberAttribute defines the way the method is invoked. If no synchronization mode is defined, the method will be invoked in the working thread of the message channel (UIThreadSynchronizationMode = IgnoreSynchronization).

    [AttributeUsageAttribute(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    public sealed class MessageSubscriberAttribute : Attribute
    {
        public MessageSubscriberAttribute(string messageChannelName) {...}
        public MessageSubscriberAttribute(string messageChannelName, UIThreadSynchronizationMode uiThreadSynchronizationMode) {...}

        public string MessageChannelName { get; private set; }
        public UIThreadSynchronizationMode UIThreadSynchronizationMode { get; set; }
    }
Below you see an example of an asynchronous invoking a method in the UI Thread

        [MessageSubscriber(Env.MainMessageChannelName, UIThreadSynchronizationMode.PostAsynchronousInUIThread)]
        private void handleAsyncOperationResponseMessage(AsyncOperationResponseMessage m)
        {
            if (m.HasError)
            {
                MessageBox.Show(m.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
To make use of the thread synchronization the SynchronizationContext must be provided. To achieve this, the ComponentContainer should not be created too early (eg. before the application runs). The optimal place for creating the ComponentContainer is the constructor of the main form or its OnLoad() method.

Last edited Jan 13, 2013 at 8:57 AM by polo, version 2

Comments

No comments yet.