Author Archives: Code Thaumaturge

Async Made Easy

During the course of working on my current project I’ve had to write many, many WCF web service calls in Silverlight. This means a lot of typing for event subscription and error handling since Silverlight requires that you use asynchronous calls. To make this process as easy as possible I implemented a series of classes centering around one which I named AsyncHandler. This class allows you to make calls to your MVVM model like the following using very few lines of code:

Model.GetUsers(
    lUsers => MyUsers = lUsers,
    lEx => ShowError("Unable to retrieve user list!"));

This style of invocation offers several advantages. First, it’s very brief. Traditionally you have to write the AsyncCompletedEventHandler function and come up with case-by-case logic for processing the error state which can be quite verbose. This also leads us to the second advantage which is that the response processing is located directly after the invocation giving it the look and feel of a synchronous call. Finally, it gives you an easy way to reuse the same model method for different purposes since the callbacks are supplied as parameters. In summation, AsyncHandler allows you to replace the standard event-driven web service model with a condensed and simplified lambda expression driven callback model.

The entire implementation is included in the collapsed code block at the bottom of this post, but I’d like to cover the three core functions that make the AsyncHandler work. The first is the AsyncHandler constructor  which takes three parameters: target is the object reference hosting the asynchronous members (typically the web service client), baseName is an optional parameter indicating the name of the async functions when stripped of their “Async” and “Complete” postfixes, and ignoreRequestId is an optional flag which disables lastest-invocation tracking.

IgnoreRequestID = ignoreRequestId;
Target = target;

// If baseName is null, infer it from the TEventArgs type name.
if (String.IsNullOrWhiteSpace(baseName))
{
    string eventArgsName = typeof(TEventArgs).Name;
    int postfixIndex = eventArgsName.IndexOf("CompletedEventArgs");
    baseName = eventArgsName.Substring(0, postfixIndex);
}

// Use reflection to find the async invocation method.
string asyncFunctionName = baseName + "Async";
MethodInfo function = target.GetType()
    .GetMethods(BindingFlags.Instance | BindingFlags.Public)
    .SingleOrDefault(lMethod =>
        lMethod.Name.Equals(asyncFunctionName,
                            StringComparison.OrdinalIgnoreCase) &&
        FunctionHasUserObjectParameter(lMethod));
if (function == null)
    throw new EntryPointNotFoundException(
        String.Format("Async function \"{0}\" not found",
                      asyncFunctionName));
Function = function;

// Use reflection to find the completed event and subscribe to it.
string completedEventName = baseName + "Completed";
EventInfo completedEvent = target.GetType()
    .GetEvent(completedEventName,
              BindingFlags.Instance | BindingFlags.Public);
if (completedEvent == null)
    throw new EntryPointNotFoundException(
        String.Format("Completed event \"{0}\" not found",
                      completedEventName));

completedEvent.AddEventHandler(Target,
    new EventHandler<TEventArgs>(Target_FunctionCompleted));

In a nutshell this code uses reflection to obtain references to the “Async” and “Complete” members on the supplied target. If baseName is null it will infer a value from the name of the AsyncCompletedEventArgs supplied as the first type parameter to the class. These classes are created automatically by the web service proxy generator so it is guaranteed to match the member names found on the target. The remainder of the function validates the existence of the “Async” method and the “Complete” event then stores it for use when invoking the procedure and subscribes to it respectively. At this point an AsyncHandler can be constructed as simply as this:

MyServiceClient client = new MyServiceClient();
AsyncHandler<GetUsersCompletedEventArgs> handler =
    new AsyncHandler<GetUsersCompletedEventArgs>(client);

The next core function is the Invoke function which is defined as:

public void Invoke(Delegate callback, Action<Exception> failureCallback,
                   params object[] args)
{
    if (!IgnoreRequestID)
        RequestID++;

    AsyncHelperBase helper = BuildHelper(callback);
    helper.FailureCallback = failureCallback;
    helper.IgnoreRequestID = IgnoreRequestID;
    helper.RequestID = RequestID;

    object[] argsWithHelper = null;
    if (args == null)
        argsWithHelper = new object[1];
    else
    {
        argsWithHelper = new object[args.Length + 1];
        for (int i = 0; i < args.Length; i++)
            argsWithHelper[i] = args[i];
    }
    argsWithHelper[argsWithHelper.Length - 1] = helper;

    Function.Invoke(Target, argsWithHelper);
}

Invoke uses reflection and the MethodInfo reference obtained in the constructor to begin the asynchronous call. The bulk of this method involves attaching tracking values using the optional userState parameter available on all proxy-generated “Async” methods. An AsyncHelperBase object is constructed which stores references to the success and failure callbacks and the current request ID. This object is then spliced onto the end of the args array in the position of the userState parameter and the combined array is supplied to the MethodInfo.Invoke method. One round trip to the server later and we reach our final core function:

public static void HandleComplete(
    AsyncCompletedEventArgs e,
    Action<object> successCallback,
    Action<Exception> failureCallback = null)
{
    if (e.Cancelled || e.Error != null)
    {
        if (failureCallback != null)
            failureCallback(e.Error);
    }
    else if (successCallback != null)
    {
        PropertyInfo resultProperty = e.GetType().GetProperty("Result");
        if (resultProperty == null)
            successCallback(null);
        else
        {
            object result = resultProperty.GetValue(e, null);
            successCallback(result);
        }
    }
}

This method is invoked by the event handler subscribed in the constructor. The AsyncHelperBase object constructed in the Invoke method is extracted from the AsyncCompletedEventArgs.UserState property to supply HandleComplete‘s parameters. It then checks to see if the response is in an error state and either invokes the failure callback or the success callback using reflection to evaluate the EventArgs’ Result property.

One essential feature which isn’t represented in the above code is the request ID processing. The request ID increments with each successive call to the AsyncHandler’s Invoke function. When a response comes back from the server the request ID stored in the AsyncHelperBase object is compared to the AsyncHandler’s request ID. If IgnoreRequestID is set to true or the IDs match, HandleComplete is allowed to execute. Otherwise the result is discarded. This is a very useful feature which prevents varying execution times from causing your callbacks to be invoked with stale data. If you’re intending to receive many results back in rapid succession, for example populating data from a list, it is very important to set the IgnoreRequestID flag to true.

There are a number of subclasses of AsyncHandler to address some additional optimizations and fringe cases. I encourage you to look through the complete code and don’t hesitate to ask if you feel like I skimmed over something important. Thanks for reading!

Complete AsyncHandler Implementation

using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace CodeThaumaturgy
{
    public static class AsyncTools
    {
        /// <summary>
        /// Determines the response state specified in AsyncCompletedEventArgs and invokes either successCallback
        /// or failureCallback with the appropriate arguments. Logs failures to the debugger log under the
        /// "WebServiceException" key.
        /// </summary>
        public static void HandleComplete(AsyncCompletedEventArgs e, Action<object> successCallback, Action<Exception> failureCallback = null)
        {
            if (e.Cancelled || e.Error != null)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Log(1, "WebServiceException",
                        e.Error == null ? "Cancelled" : e.Error.ToString());

                if (failureCallback != null)
                    failureCallback(e.Error);
            }
            else if (successCallback != null)
            {
                PropertyInfo resultProperty = e.GetType().GetProperty("Result");
                if (resultProperty == null)
                    successCallback(null);
                else
                {
                    object result = resultProperty.GetValue(e, null);
                    successCallback(result);
                }
            }
        }
    }

    #region Handlers

    /// <summary>
    /// Base implementation of the AsyncHandler framework for processing weakly typed result values. Handles async
    /// event subscription and leverages AsyncHelpers to invoke supplied callbacks.
    /// </summary>
    public class AsyncHandler<TEventArgs> where TEventArgs : AsyncCompletedEventArgs
    {
        public bool IgnoreRequestID { get; protected set; }
        public int RequestID { get; protected set; }
        public object Target { get; protected set; }

        protected MethodInfo Function { get; set; }

        /// <param name="target">The object containing the async function call and the corresponding completed event.</param>
        /// <param name="baseName">
        ///     The name of the async function. This will be "X" for a function with async members named "XAsync"
        ///     and "XCompleted". If this value is supplied or defaulted as null it will be inferred from the type name
        ///     of TEventArgs.
        /// </param>
        /// <param name="ignoreRequestId">
        ///     If this is set to false (the default) only the latest invocation's response will result in a callback in
        ///     the case of multiple concurrent requests. If this is set to true, there will be a 1:1 invocation / callback
        ///     relationship, but as with any asynchronous system there is no guarantee that the results will come back in
        ///     the same order in which the initial invocations were made.
        /// </param>
        public AsyncHandler(object target, string baseName = null, bool ignoreRequestId = false)
        {
            if (target == null)
                throw new ArgumentNullException("target");

            IgnoreRequestID = ignoreRequestId;
            Target = target;

            // If baseName is null, infer it from the TEventArgs type name.
            if (String.IsNullOrWhiteSpace(baseName))
            {
                string eventArgsName = typeof(TEventArgs).Name;
                int postfixIndex = eventArgsName.IndexOf("CompletedEventArgs");
                baseName = eventArgsName.Substring(0, postfixIndex);
            }

            // Use reflection to find the async invocation method.
            string asyncFunctionName = baseName + "Async";
            MethodInfo function = target.GetType()
                .GetMethods(BindingFlags.Instance | BindingFlags.Public)
                .SingleOrDefault(lMethod => lMethod.Name.Equals(asyncFunctionName, StringComparison.OrdinalIgnoreCase) &&
                                            FunctionHasUserObjectParameter(lMethod));
            if (function == null)
                throw new EntryPointNotFoundException(String.Format("Async function \"{0}\" not found", asyncFunctionName));
            Function = function;

            // Use reflection to find the completed event and subscribe to it.
            string completedEventName = baseName + "Completed";
            EventInfo completedEvent = target.GetType()
                .GetEvent(completedEventName, BindingFlags.Instance | BindingFlags.Public);
            if (completedEvent == null)
                throw new EntryPointNotFoundException(String.Format("Completed event \"{0}\" not found", completedEventName));

            completedEvent.AddEventHandler(Target, new EventHandler<TEventArgs>(Target_FunctionCompleted));
        }

        private static bool FunctionHasUserObjectParameter(MethodInfo methodInfo)
        {
            ParameterInfo lastParameter = methodInfo.GetParameters().LastOrDefault();
            return lastParameter != null &&
                   typeof(object).Equals(lastParameter.ParameterType) &&
                   lastParameter.Name.Equals("userState", StringComparison.OrdinalIgnoreCase);
        }

        public void InvalidateRequest() { RequestID++; }

        /// <summary>
        /// Creates the AsyncHelper tracking object and invokes the async method stored by the constructor in the
        /// Function property.
        /// </summary>
        /// <param name="callback">The callback to invoke when a successful response is received.</param>
        /// <param name="failureCallback">The callback to invoke when an error occurs.</param>
        /// <param name="args">The arguments to supply to the async function.</param>
        public void Invoke(Delegate callback, Action<Exception> failureCallback, params object[] args)
        {
            if (!IgnoreRequestID)
                RequestID++;

            AsyncHelperBase helper = BuildHelper(callback);
            helper.FailureCallback = failureCallback;
            helper.IgnoreRequestID = IgnoreRequestID;
            helper.RequestID = RequestID;

            object[] argsWithHelper = null;
            if (args == null)
                argsWithHelper = new object[1];
            else
            {
                argsWithHelper = new object[args.Length + 1];
                for (int i = 0; i < args.Length; i++)
                    argsWithHelper[i] = args[i];
            }
            argsWithHelper[argsWithHelper.Length - 1] = helper;

            try { Function.Invoke(Target, argsWithHelper); }
            catch (Exception ex)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Log(4, "AsyncHelperInvoke", ex.ToString());
                throw ex;
            }
        }

        protected virtual AsyncHelperBase BuildHelper(Delegate callback)
        {
            if (callback != null && !(callback is Action))
                throw new ArgumentException("Must be of type Action", "callback");

            return new AsyncHelper() { Callback = (Action)callback };
        }

        protected void Target_FunctionCompleted(object sender, TEventArgs e)
        {
            AsyncHelperBase helper = (AsyncHelperBase)e.UserState;
            helper.HandleComplete(RequestID, e);
        }
    }

    /// <summary>
    /// Subclass of AsyncHandler for invoking async calls with a void return type.
    /// </summary>
    public class AsyncHandler : AsyncHandler<AsyncCompletedEventArgs>
    {
        public AsyncHandler(object target, string baseName, bool ignoreRequestId = false) : base(target, baseName, ignoreRequestId) { }
    }

    /// <summary>
    /// Subclass of AsyncHandler which returns strongly typed results.
    /// </summary>
    public class AsyncHandler<TEventArgs, TReturn> : AsyncHandler<TEventArgs> where TEventArgs : AsyncCompletedEventArgs
    {
        public AsyncHandler(object target, bool ignoreRequestId = false)
            : base(target, null, ignoreRequestId)
        {
        }

        protected override AsyncHelperBase BuildHelper(Delegate callback)
        {
            if (callback != null && !(callback is Action<TReturn>))
                throw new ArgumentException(String.Format("Must be of type Action<{0}> callback", typeof(TReturn).FullName));

            return new AsyncHelper<TReturn>() { Callback = (Action<TReturn>)callback };
        }

        public void TypedInvoke(Action<TReturn> callback, Action<Exception> failureCallback, params object[] parameters)
        {
            Invoke(callback, failureCallback, parameters);
        }
    }

    #endregion Handlers

    #region Helpers

    /// <summary>
    /// Stores references to callback delegates. Provides a generalized callback invocation method to support callbacks
    /// with varying type parameters and logic for discarding stale results using an externally populated RequestID property.
    /// </summary>
    public abstract class AsyncHelperBase
    {
        public Action<Exception> FailureCallback { get; set; }
        public bool IgnoreRequestID { get; set; }
        public int RequestID { get; set; }

        public void HandleComplete(int requestId, AsyncCompletedEventArgs e)
        {
            if (!IgnoreRequestID && RequestID != requestId)
                return;

            AsyncTools.HandleComplete(e, (result) => { InvokeCallback(result); }, FailureCallback);
        }

        protected abstract void InvokeCallback(object result);
    }

    public class AsyncHelper : AsyncHelperBase
    {
        public Action Callback { get; set; }

        protected override void InvokeCallback(object result)
        {
            if (Callback != null)
                Callback.Invoke();
        }
    }

    public class AsyncHelper<T> : AsyncHelperBase
    {
        public Action<T> Callback { get; set; }

        protected override void InvokeCallback(object result)
        {
            if (Callback != null)
                Callback.Invoke((T)result);
        }
    }

    #endregion Helpers
}

MVVM Model Examples

public class ExampleModel : IExampleModel
{
    private ExampleServiceClient _exampleClient;
    private ExampleServiceClient ExampleClient
    {
        get
        {
            if (_exampleClient == null)
                _exampleclient = new ExampleServiceClient();
            return _exampleClient;
        }
    }

    // This method uses a subclass of AsyncHandler<TEventArgs> which takes
    // a second type parameter of the return type. This allows for the
    // easy use of strongly typed callback delegates.
    private AsyncHandler<GetUsersCompletedEventArgs, IEnumerable<User>> _getUsersHandler;
    public void GetUsers(Action<IEnumerable<User>> callback,
                         Action<Exception> failureCallback = null)
    {
        if (_getUsersHandler == null)
            _getUsersHandler = new AsyncHandler<GetUsersCompletedEventArgs, IEnumerable<User>>(ExampleClient);
        _getUsersHandler.TypedInvoke(callback, failureCallback);
    }

    // This method uses another subclass which uses the base
    // AsyncCompletedEventArgs type parameter indicating that there is a
    // null return type. The success callback is optional in this case.
    // Note that the ignoreRequestId flag is set to true so the callback
    // will be invoked for every save attempted.
    private AsyncHandler _saveUserHandler;
    public void SaveUser(User user,
                         Action callback = null,
                         Action<Exception> failureCallback = null)
    {
        if (_saveUserHandler == null)
            _saveUserHandler =
                new AsyncHandler(ExampleClient, "SaveUser", true);
        _saveUserHandler.Invoke(callback, failureCallback, user);
    }
}

One VisibilityConverter to Rule Them All

One long-running irritation I’ve had with the Silverlight XAML rendering engine is that it refuses to make a best guess for values when bound to an element’s Visibility property. One would think that binding a boolean value to Visibility would make sense in particular, but unless the value is a System.Windows.Visibility enumeration value your binding will silently fail to update the binding target. To resolve this frustration, I created a custom VisibilityConverter IValueConverter implementation that maps most common data types in a sane way.

In short, this implementation compares the type of the supplied “value” parameter against a series of known types. When a match is found, it applies individualized logic to determine whether to return Visibility.Visible or Visibility.Collapsed.

public class VisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        bool isVisible = false;

        if (value is bool || value is bool?)
            isVisible = (bool?)value == true;
        else if (value is double) isVisible = (double)value != 0;
        else if (value is long) isVisible = (long)value != 0;
        else if (value is int) isVisible = (int)value != 0;
        else if (value is float) isVisible = (float)value != 0;
        else if (value is short) isVisible = (short)value != 0;
        else if (value is byte) isVisible = (byte)value != 0;
        else isVisible = value != null;

        if (ObjectToBool(parameter))
            isVisible = !isVisible;

        return isVisible ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        throw new InvalidOperationException();
    }
}

You’ll note at the end the call to ObjectToBool(…). This allows you to invert the behavior of the VisibilityConverter, which is particularly useful for addressing error conditions, using the converter parameter such that falses, 0′s, and nulls become visible. Since the parameter type can vary depending on whether it’s supplied from a static resource or entered as a string in the binding expression by hand, a special function is required for resolving it.

public static bool ObjectToBool(object boolObject, bool nullValue = false)
{
    bool toggle = false;

    if (boolObject != null)
    {
        if (boolObject is bool)
            toggle = (bool)boolObject;
        else if (boolObject is bool?)
            toggle = (bool?)boolObject == true;
        else if (boolObject is string)
        {
            if (!Boolean.TryParse((string)boolObject, out toggle))
                toggle = false;
        }
    }
    else
        toggle = nullValue;

    return toggle;
}

A trick that I’ve found to be very helpful is to define some of these general purpose converters in your App.xaml file, which allows them to be accessed from any controls you have in your project using a static resource reference. Here’s an example of what that might look like.

<TextBlock Text="No results found."
           Visibility="{Binding Path=Results.Count,
                        Converter={StaticResource VisibilityConverter},
                        ConverterParameter=True}" />

Hope this helps, and please post if you have any ideas on how to simplify this any further!


Customizing the PivotViewer

For those of you who haven’t seen it yet, Microsoft released a very powerful data visualization control called the PivotViewer. It leverages the deep zoom feature to perform filtering and sorting of complex data objects allowing the user to navigate through dense data in an efficient (and fun) way. The only problem is that it is a closed source library and the control implementation doesn’t allow for templates or styling.

Luckily there are a few tricks you can play to make substantial changes to the appearance and behavior of the PivotViewer if you’re willing to work with the codebehind. Xpert360 Ltd. published a blog post titled Adventures with PivotViewer in which they explain how to effectively re-skin the PivotViewer. After rifling through the assemblies using Reflector I found that you can get access to much more of the core functionality by leveraging some of the classes exposed through the library’s internal namespace.

The PivotViewer control that they give you access to through the System.Windows.Pivot namespace is a wrapper around the CollectionViewer MVVM structure exposed in the Microsoft.Pivot.Internal.* namespaces. Almost all of the members that you would wish to be able to modify are exposed by obtaining references to the view, view model, and model. This can be achieved trivially by subclassing PivotViewer and overriding the OnApplyTemplate() function.

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    Grid partContainer = (Grid)this.GetTemplateChild("PART_Container");

    CollectionViewerView cvv =
        ((CollectionViewerView)(partContainer).Children[0]);
    CollectionViewerViewModel cvvm =
        (CollectionViewerViewModel)ViewBehaviors.GetViewModel(cvv);
    CollectionViewerModel cvm =
        (CollectionViewerModel)ViewBehaviors.GetModel(cvv);
}

Once you obtain these three references, the sky is the limit. One example of what I was able to use these for was changing the default view. The data that I am displaying lends itself almost exclusively to the histogram view, but the default is the grid view. Whenever the sort category was changed automatically by drilling down through a single histogram column the view was reset to grid view. This resulted in an unpleasant user experience because it required mousing all the way across the screen to keep setting the view back to histogram mode.

I was again able to leverage Reflector to find that the views are initialized into a ViewSelectionState object exposed through a property on the model. Each view has an entry in the ViewDataObjects array on the ViewSelectionState, with the grid view data object in the first index and the histogram in the second. By reversing them in the OnApplyTemplate() function I was able to change the default behavior of the PivotViewer.

cvm.ViewSelectionState.ViewDataObjects =
    cvm.ViewSelectionState.ViewDataObjects
        .Reverse()
        .ToArray();

Another useful feature I was able to add was a GridSplitter next to the filter panel. Many of our values are long and were being trimmed by the filter panel, so by adding the GridSplitter I was able to give users access to the complete values as necessary. This improvement leveraged the view reference to modify the visual tree.

FrameworkElement filterPane =
    (FrameworkElement)cvv.FindName("PART_FilterPaneContainer");
Grid filterParent = (Grid)filterPane.Parent;

GridSplitter splitter = new GridSplitter();
splitter.SetValue(Grid.ColumnProperty, 0);
splitter.Style =
    (Style)App.Current.Resources["RightVerticalGridSplitterStyle"];
BindingOperations.SetBinding(splitter, GridSplitter.VisibilityProperty,
    new Binding("Opacity")
    {
        Source = filterPane,
        // Custom implementation converting 0 to false, other to true
        Converter = new VisibilityConverter()
    });
filterParent.Children.Add(splitter);

filterPane.Margin = new Thickness(
    filterPane.Margin.Left,
    filterPane.Margin.Top,
    filterPane.Margin.Right + splitter.Width,
    filterPane.Margin.Bottom);

Please leave a post if you come up with any other useful tweaks!


Dispatcher.DelayedInvoke

There are many cases when a developer wants a delayed action to occur. This may be a simple timed reaction to a user event, a web service poll or retry loop, or any variety of task. If you’re feeling creative you could use a Storyboard or a complicated thread implementation, but I’d like to share an elegant solution that allows you to write delayed invokes on the UI thread like this:

Dispatcher.DelayedInvoke(TimeSpan.FromSeconds(30), () => { DoStuff(); });

This syntax is possible by leveraging the Extension Method notation. For those unfamiliar with extension methods, the general idea is that it is possible to define a static function where the first parameter is defined with a “this” keyword in front of it. This indicates to the compiler that any instance of the type of that first parameter should have the function applied to it. For example:

// Note the "this" prefix before the type specification.
public static string GetFullName(this User user)
{
	return String.Format("{0}, {1} {2}",
		user.LastName, user.FirstName, user.MiddleInitial);
}

public void TestFunction()
{
	User user = new User("John", String.Empty, "Doe");
	string fullName = user.GetFullName();
}

The real power of these extension methods is that you can add additional functionality to objects that are externally instantiated or that aren’t inheritable. The Dispatcher class is a perfect example of both. It is a sealed class, and the Dispatcher references exposed through the property on DependencyObjects is instantiated by the framework.

Getting back to the issue of the DelayedInvoke extension method, I decided to use a Thread with Sleep implementation so as not to use up a ThreadPool thread. There are many ways to implement a wait, and you can easily swap in another approach. Here is my full implementation:

public static class DispatcherExtensions
{
    // Invocation without arguments.
    public static void DelayedInvoke(this Dispatcher dispatcher, TimeSpan delay, Action action)
    {
        Thread thread = new Thread(DoDelayedInvokeByAction);
        thread.Start(new Tuple<Dispatcher, TimeSpan, Action>(dispatcher, delay, action));
    }

    private static void DoDelayedInvokeByAction(object parameter)
    {
        Tuple<Dispatcher, TimeSpan, Action> parameterData = (Tuple<Dispatcher, TimeSpan, Action>)parameter;

        Thread.Sleep(parameterData.Item2);

        parameterData.Item1.BeginInvoke(parameterData.Item3);
    }

    // Invocation with arguments.
    public static void DelayedInvoke(this Dispatcher dispatcher, TimeSpan delay, Delegate d, params object[] args)
    {
        Thread thread = new Thread(DoDelayedInvokeByDelegate);
        thread.Start(new Tuple<Dispatcher, TimeSpan, Delegate, object[]>(dispatcher, delay, d, args));
    }

    private static void DoDelayedInvokeByDelegate(object parameter)
    {
        Tuple<Dispatcher, TimeSpan, Delegate, object[]> parameterData = (Tuple<Dispatcher, TimeSpan, Delegate, object[]>)parameter;

        Thread.Sleep(parameterData.Item2);

        parameterData.Item1.BeginInvoke(parameterData.Item3, parameterData.Item4);
    }
}

It’s important to note that the thread work function calls the Dispatcher‘s BeginInvoke function. The main reason for exposing the DelayedInvoke function as an extension of the Dispatcher is that it is implicit that the callback be performed on the UI thread. Even when the DelayedInvoke function is called from a non-UI thread, all operations performed in the supplied delegate can be safely made against UI objects because of the Dispatcher.BeginInvoke call.

Hopefully this makes your life a little easier.


Silverlight vs. HTML5

I was watching Giorgio Sardo’s presentation on HTML5 for Silverlight Developers at MIX 11 this morning and it got me thinking about the long term viability of Silverlight in light of the meteoric rise of HTML5. It doesn’t take much internet searching to turn up a lot of mudslinging in the language debate, but I think it’s important to step back and consider each of these languages objectively as possible for their strengths. To me this boils down to portability vs. functionality.

There is no comparison on the portability front. HTML5 is the clear winner, having broad support on essentially all platforms including low-power and mobile devices. Because Silverlight is a closed platform, open-source runtimes (See Moonlight) lag behind in their implementations of new features. Between adoption rates for Silverlight on Windows machines hovering between 60% and 70% and the limited implementations available on other operating systems, if portability is a major concern for your project there’s really no way to beat HTML5. This isn’t to say that Silverlight should be written off as irrelevant moving forward, however.

As Giorgio points out in his presentation, HTML5 exists today because of the legacy that browser plugins have provided. Most of the features that it offers have been available in Flash and Silverlight for many years, and they are drawn from these frameworks in an attempt to replicate the user and developer experiences in an open, cross-platform way. These plugins have set the standard for what users expect on the internet, and despite all of the hype about the HTML5 being the next big thing, Flash and Silverlight still continue to set the pace for new features.

This isn’t to say that the flow of ideas is entirely a one way street. There are a lot of smart people working on the HTML5 standard and writing libraries to support it. The fact of the matter is though that the HTML5 standard is maintained by a large consortium of powerful entities, sometimes with conflicting interests and voices. There is a lot of inertia when making changes to such a widely distributed standard as HTML when compared to a proprietary closed standard. Microsoft has a clear direction for their Silverlight platform and the executive clout to make platform improvements happen in a timely manner.

In most cases neither HTML5 nor a plugin framework like Silverlight or Flash are perfectly suited for any particular development task. In fact, compared side-by-side they are all almost identical in their capabilities. When it comes time to decide which language to use for a new web-based project it comes down to weighing the portability vs. functionality question I opened this post with.

The greatest strength of HTML5 is that your application can be written once and deployed anywhere. This is of particular benefit when creating something for consumption by the general public where you are guaranteed to see a wide variety of client configurations. If this portability isn’t a great concern, for example in an enterprise environment, then the bleeding-edge technological benefit of using a plugin based framework like Silverlight may outweigh it.


Introduction

This is a brand new blog for me so I’d like to take a moment to talk about who I am and why I’m starting this blog. I’ll be filling out more of my personal details with regard to my experience on the “About” page, but in short, I’m currently a Silverlight developer. I work at an electronics manufacturing company in Beaverton, Oregon called Vanguard EMS developing software tools for optimizing their internal processes. By education, I’m a physicist, but I got into coding as a kid and ended up doing it professionally because I love it!

The idea behind this blog is to give me an avenue for publishing some of the tips, tricks, and opinions I’ve come up with over the course of my journey through software development. The internet has proven to be an invaluable resource when solving problems, and I feel like it’s my duty to help give back to the online community. I promise to do my best to provide useful information without boring you to death or forcing you to wade through paragraphs of drivel for the good stuff.

With that, I have a beta deployment to address. Stay tuned!


Follow

Get every new post delivered to your Inbox.