New UIDispatchMessageBase Class

May 13, 2011 at 5:40 AM

Hi

Really often I want to load data in a backthread which is later shown in the UI and because I think many people have this scenario I'd like to share my idea/solution.

Perhaps someone finds it usefule or furthermore it could be interesting for the MVVM Light Toolkit.

Comments are welcome :-)

In the beginning I created messages which are received by a listeners who were directing the messages to the components, retrieving the result and calling a callback.

It looked Like This

 


//Create the RequestMessage with a callback
...
 RequestCustomerMessage myMsg = new RequestCustomerMessage(myConditionalClause,(result)=> this.processResult(result));
Task.Factory.StartNew(()=>this.MessengerInstance.Send<RequestCustomerMessage>(myMsg)));
...

private void processResult(IEnumerable<Customer> customers)
{
 DispatcherHelper.UIDispatcher.Invoke(new Action(() this.=> dispatchedProcess(customers)), this.UIDispatchPriority, null);
}

This is quite a lot of redundant infrastructure code.

 

So I created a new subclass based on MessageBase -> "UIDispatchMessageBase"


  /// <summary>
    /// Base for all Messages with a reply to a UI Thread.
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    public abstract class UIResponseMessage<TResult> : MessageBase    {
        /// <summary>
        /// Gets or sets the _ reply action.
        /// </summary>
        /// <value>
        /// The _ reply action.
        /// </value>
        private Action<TResult> _ReplyAction { getset; }
 
     
        /// <summary>
        /// Initializes a new instance of the <see cref="UIResponseMessage&lt;TResult&gt;"/> class.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="response">The action which should be triged for the reply</param>
        public UIResponseMessage(Action<TResult> response,object sender)
            : base(sender)
        {
            this._ReplyAction = response;
            this.setDefaults();
        }
 
        /// <summary>
        /// Initializes a new instance of the <see cref="UIResponseMessage&lt;TResult&gt;"/> class.
        /// </summary>
        /// <param name="sender">The message's original sender.</param>
        /// <param name="target">The message's intended target. This parameter can be used
        /// to give an indication as to whom the message was intended for. Of course
        /// this is only an indication, amd may be null.</param>
        /// <param name="response">The action which should be triged for the reply</param>
        public UIResponseMessage(Action<TResult> response, object sender,TaskCreationOptions options)
            : base(sender,options)        
        {
            this._ReplyAction = response;
            this.setDefaults();
        }
 
 
 
        /// <summary>
        /// Sets the defaults.
        /// </summary>
        private void setDefaults()
        {
            this.UIDispatchPriority = DispatcherPriority.Background;
        }
 
 
        /// <summary>
        /// Gets or sets the UI dispatch priority.
        /// </summary>
        /// <value>
        /// The UI dispatch priority.
        /// </value>
        public DispatcherPriority UIDispatchPriority { getset; }
 
        /// <summary>
        /// Sends a response to the sender of this message
        /// </summary>
        /// <param name="response">The response.</param>
        public void Reply(TResult response)
        {
            Action<TResult> replyHandler = this._ReplyAction;
 
            if (replyHandler != null)
            {
                DispatcherHelper.UIDispatcher.Invoke(new Action(() => replyHandler(response)), this.UIDispatchPriority, null);
            }
        }
    }

this class automatically dispatches the result back on the ui thread.

Also I'm currently working on creating a abstract listener which will transparently automise the backthread invokation (if requested). For this I'd change the class hirachy to
MessageBase->AsyncMessageBase->UIDispatchMessageBase

When the Listener retrieves a AsyncMessageBase it will automatically start the background UI Thread.


Comments are welcome :-)