Click here to Skip to main content
12,350,971 members (32,515 online)
Click here to Skip to main content

Stats

14.3K views
112 downloads
25 bookmarked
Posted

A Simple Solution to Some Problems with Asynchrony in Silverlight

, 9 Mar 2010 CPOL
A small, extensible suite of classes that elegantly solve some common problems involving asynchrony and event handling that tend to occur when Silverlight and WCF are used together.
using System;
using System.Collections.Generic;

namespace TaskManagerDemo.Utility
{
    /// <summary>
    /// Subterfuge required to get around the compiler being just a teeny bit too strict.
    /// </summary>
    /// <param name="sender">An event handler's sender argument.</param>
    /// <param name="e">An event handler's EventArgs (or derived-class) argument.</param>
    public delegate void GenericEventHandler(object sender, object e);

    /// <summary>
    /// Facilitates queueing of the processing of results from a sequence of asynchronous service method calls.
    /// </summary>
    public class QueuedAsyncServiceCallManager : AsyncServiceCallManager
    {
        /// <summary>
        /// Gets / sets an indicator that the async service call has returned its result
        /// (the associated ...AsyncCompleted event handler has been called).
        /// </summary>
        public bool ResultReturned { get; set; }

        /// <summary>
        /// Represents a task that must be in Completed Status before processing of the returned result can begin;
        /// Basically places this task and the Prerequisite task in a queue.
        /// </summary>
        public TaskManager Prerequisite { get; set; }

        // Event handler(s) to be called when the Prerequisite task reaches Completed Status.
        private List<EventProcessor> _eventProcessorList = new List<EventProcessor>();

        // C'tor.
        public QueuedAsyncServiceCallManager(string name) : base(name) { }

        /// <summary>
        /// Adds the specified event handler and its arguments to the list of handlers associated with this task that will be
        /// called when the Prerequisite task reaches Completed status, OR
        /// Calls the event handler with its arguments immediately if the Prerequisite task is null or already in Completed
        /// Status. 
        /// </summary>
        /// <param name="handler">An event handler, usually an ...AsyncCompleted event handler.</param>
        /// <param name="e">The EventArgs or derived-class object associated with / required by the specified event handler.
        /// </param>
        public void EnqueueResultHandling(GenericEventHandler handler, object sender, EventArgs e)
        {
            EventProcessor ep = new EventProcessor { Handler = handler, Sender = sender, Args = e };
            if (Prerequisite == null || Prerequisite.Status == TaskStatus.Completed)
            {
                ep.Handler(ep.Sender, ep.Args);
            }
            else
            {
                if (!_eventProcessorList.Contains(ep))
                {
                    _eventProcessorList.Add(ep);
                    Prerequisite.StatusChanged += new EventHandler<EventArgs>(Prerequisite_StatusChanged);
                }
            }
        }

        // Handler for the Prequisite task's StatusChanged event.
        private void Prerequisite_StatusChanged(object sender, EventArgs e)
        {
            if (Prerequisite == null || Prerequisite.Status == TaskStatus.Completed)
            {
                foreach (EventProcessor ep in _eventProcessorList)
                {
                    ep.Handler(ep.Sender, ep.Args);
                }
                _eventProcessorList.Clear();
            }
            else
            {
                ResultReturned = false;
            }
        }

        // Encapsulates an event handler with its arguments and enables determination of equality and thus
        // identification of duplicates.
        private class EventProcessor : IEquatable<EventProcessor>
        {
            public GenericEventHandler Handler { get; set; }
            public object Sender { get; set; }
            public object Args { get; set; }

            #region IEquatable<EventProcessor> Members

            public bool Equals(EventProcessor other)
            {
                return (Handler.Equals(other.Handler) && Sender.Equals(other.Sender) && Args.Equals(other.Args));
            }

            #endregion IEquatable<EventProcessor> Members
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

George Henry 1954
Software Developer (Senior) Concur
United States United States
George Henry has worked as a software developer for more than 20 years. He is currently employed by Concur in Bellevue, Washington, USA.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160621.1 | Last Updated 9 Mar 2010
Article Copyright 2009 by George Henry 1954
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid