XBAPs and Bitmap Effects

|

It has be a while since I last put together an XBAP (XAML Browser Application), so the myriad of security hurdles that one has to overcome has long since vanished from my short term memory; to the point where I am having to re-learning things. Bugger, I hate that! With that in mind, the purpose of this post is to document something I have rediscovered about XBAP’s and bitmap effects, in an attempt to help me remember and not have to keep relearning the same stuff.

So first off, bitmap effects are cool; they add a certain pizzazz to your UI, and if used subtly they really can make a big difference in the visual appeal of your UI:

image

However, you cannot use the BitmapEffect property on the UIElement class in an XBAP – note that UIElement is very high in the object hierarchy for WPF, so just about all visual elements contain this property by way of UIElement and then FrameworkElement; here is how you would use a BitmapEffect in XAML:

<Image Source="Images\Cube.png">
    <Image.BitmapEffect>
        <BevelBitmapEffect/>
    </Image.BitmapEffect>
</Image>

Attempting to run this XAML from within an XBAP, with the default configuration of Partial Trust, you see the following error message:

image

Interestingly, this is not a SecurityException, but simply a XamlParseException. However, if you are running in debug mode and happen to check the Output window, you see the following:

image

Note that the second to last line is a SecurityException, so the reason that the XAML cannot be parsed is due to a security failure. If you remove the BitmapEffect from the XAML, and only the BitmapEffect, all works as you would expect. From my experience this is the typical developer experience when falling over a partial trust issue, note that the SecurityException contains no additional information, let the needle in a haystack search begin; but more on that later.

It is also worth noting that WPF has matured, and is now able to leverage the GPU in your graphics card (or an approximation in software) by way of the Effect class. I am sure that there are some really awesome explanations as to how that works and what that is all really about, but that is not what this post is all about (if you know of a good explanation then please let leave a comment at the end of the post). From the point of view of a developer who has little interest in creating their own effects, to make use of this great feature simply use the new shiny Effect property, also found on the UIElement class, introduced in WPF 3.5 SP1.

However, WPF also does not allow an Effect class instance in Partial Trust – and therefore you still cannot use one in an XBAP without changing the permission requests. It is worth pointing out that not all the previous bitmap effects have been implemented as Effect‘s; at the time of writing there are only three:

  • BlurEffect
  • DropShadowEffect
  • ShaderEffect (used for creating custom effects)

Meaning that we cannot make use of the GPU today for the following type of effects:

  • Bevel
  • Emboss
  • OuterGlow

Personally, I do not think that this is any great loss, as the only effect that I miss is the OuterGlowBitmapEffect; it may well serve as a good catalyst to prompt me to learn a little more about creating my own effects.

To add an Effect to your application you use the following XAML:

<Image Source="Images\Cube.png" >
    <Image.Effect>
        <BlurEffect/>
    </Image.Effect>
</Image>

Attempting to run this XAML from within an XBAP, with the default configuration of Partial Trust, you see the following error message:

image

This time, while it is a XamlParseException, as before, but Microsoft have massively improved the exception handling with these effects as they actually tell me WHY it has failed: Request for the permission of type ‘System.Security.Permissions.UIPermission’ failed. Awesome, this means I can “tweak” my security settings to get the application to run when using an Effect:

image

Now this is the only permission I have to change, I do not have to make my whole application run in Full Trust to use the effects. I can take this a step further in for my application by configuring the properties of the specific permission, to prevent access to the Clipboard, if the application does not need it:

image

So thanks to the better error reporting when using the Effect’s classes in a partial trust environment, I can now successfully isolate just the permission I need, and make a calculated decision as to whether this is something the application really needs. Note however, tweaking this permission does not work when using the BitmapEffect classes, I still have not found that needle in the haystack yet.

image

So while I cannot show you the application running in the wild due to the “extra” permission required (click the image above to see the security error), the screenshot above does show the application running in my environment, where I’m happy to allow the application the permission it requires, which is perfect for an intranet or extranet environment. Alternatively, I could sign the application with an SSL certificate and you could trust that.

Finally, I want to talk quickly about the analyzer tool in Visual Studio 2008. The purpose of the tool is to work out if your application can run in partial trust; it is good at telling me if I need to run in full trust or not, which is very helpful, but it is really poor at telling me WHY! Making it really, really, really hard to fix these violations of partial trust, especially in these cases where I cannot easily remember all the details of what you can and cannot do, or if you are a newbie. As we have seen they have improved the exception handling for an Effect, however, I sincerely hope for more improvements with WPF 4.0 in this area. If anyone knows of any other tooling or a better way to keep on top of this issue, I would love to hear from you.

I hope this has been useful, as it was only a small “nice to have” feature that I added to one of my applications and it threw for me quite a while to isolate the problem and get the XBAP working at all, never mind the effects; but it was useful to also explore both BitmapEffect and Effect and work out the differences.

As usual if you have any comments, questions, flames, enhancements I would love to hear from you. In the meantime, think deeply and enjoy.

Invalidate Often, Update Once

|

I’ve recently been watching a bunch of the longer sessions from MIX09, mainly Hiking Mount Avalon and Robbie Ingebretsen’s session(s) Design Fundamentals for Developers; both of which are about 3 hours long but well worth the time spent watching.

During these sessions I’ve taken copious notes (by using Evernote) and for a few of the more complex and/or unexplored topics I want to write a post, as well as put together some code, on my own to make sure I’ve understood the concept, and to generally share the wealth: this is first post in what I suspect will be a series.

This post is about updating UI elements on the UI thread. A lot. Time consuming updates. On the UI thread. A lot of updates.

The example application I’ve written to discuss this technique is described by the following class diagram:

ObjectModel_UpdateOnce1

And this screenshot:

UI_UpdateOnce1

The application consists of a ListBox where the ItemsSource property is set to an ObservableCollection<int>, and then when the Add Items button is clicked a method called OnAddItems appends ten thousand random integer values to the collection. There is also a listener wired to the CollectionChanged event on the ObservableCollection<int>, which simply invokes a method called UpdateTotal that adds up all the integers currently in the collection, and then presents the calculated value in the UI as the Total.

What this application is attempting to simulate is a situation where a large number of items need to be added to the UI in quick succession, but where there is also some additional action required after an item has been added, a calculated value in the example application. Here’s the code for OnAddItems, OnCollectionChanged and UpdateTotal which outlines how these methods interact:

private void OnAddItems(object sender, RoutedEventArgs e)
{
    Random rnd = new Random((int)DateTime.Now.Ticks);
    for (int i = 0; i < 10000; i++)
        this.list.Add(rnd.Next(0, 100));
}

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    UpdateTotal();
}

private void UpdateTotal()
{
    int total = 0;
    foreach (var item in this.list)
        total += item;

    this.Total.Text = total.ToString();
}

The problem with the code is simply that it’s too noisy on the UI thread. The OnCollectionChanged method is called ten thousand times, and the list is totalled ten thousand times as each integer and the UI is also updated tens of thousands of times. Obviously this example is a little contrived but I’m sure you can think of some real world scenarios or maybe you’ve seen code like this in the wild.

To give you some idea of how the performance degrades on my machine here’s the debug output for this sample application, which displays the total time it takes, in milliseconds, along with how many items are currently in the list; remember that ten thousand items are appended each time Add Items is clicked:

Time taken (milliseconds): 787.375,   # List Items: 10000
Time taken (milliseconds): 2084.1261, # List Items: 20000
Time taken (milliseconds): 3344.678,  # List Items: 30000
Time taken (milliseconds): 4715.5841, # List Items: 40000
Time taken (milliseconds): 5948.9176, # List Items: 50000
Time taken (milliseconds): 7232.911,  # List Items: 60000

Assuming that we all agree that while this is a contrived example it is still a real world problem that needs a solution; and that solution is the WPF Dispatcher and a single boolean flag. Take a look at the following video that I put together to demonstrate how badly the current code impacts the UI thread, and how massive the improvement is by using the Dispatcher and an invalidate approach, as opposed to update approach:

Here are the the changes to OnCollectionChanged and UpdateTotal methods, and the new InvalidateTotal method that makes this approach work:

private bool isTotalValid;

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    InvalidateTotal();
}

private void InvalidateTotal()
{
    if (this.isTotalValid)
    {
        this.isTotalValid = false;
        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
        {
            UpdateTotal();
        });
    }
}

private void UpdateTotal()
{
    int total = 0;
    foreach (var item in this.list)
        total += item;

    this.Total.Text = total.ToString();
    this.isTotalValid = true;
}

With the code above, a new flag has been introduced: isTotalValid, which indicates whether the UpdateTotal method should be called. The OnCollectionChanged method no longer invokes UpdateTotal directly, instead it calls a new method called InvalidateTotal. The new method checks the isTotalValid flag, and if the total is valid promptly marks the total as invalid and queues a asynchronous call to UpdateTotal by using the Dispatcher.

By doing this the call to UpdateTotal has been placed on the Dispatcher’s message queue behind the currently executing call, effectively delaying the call to the UpdateTotal method until after the current thread becomes idle or the scheduler decides to let someone else have a turn, meaning that in most cases the UpdateTotal method is called only once, but InvalidateTotal is called thousands of times. Finally, the UpdateTotal method marks the total as valid once more, and the cycle begins again.

The key takeaway here, is invalidate rather than update; this is an approach adopted all over WPF, and one that I will certainly be adopting in my WPF code. I also want to offer a big thank you to Robby Ingebretsen, Jaime Rodriguez, Mike Hillberg, Lee Brenner, Laurent Bugnion and particularly for his help with this post Jonathan Russ, who explained this concept in the Hiking Mount Avalon session.

You can download the sample application from here: PaulJ.InvalidateOftenUpdateOnce.zip

As usual if you have any comments, questions, flames, enhancements I would love to hear from you. In the meantime think deeply and enjoy.

ICloneable, a perspective on the current guidelines

|

To be talking about an interface this old might seem strange, but I’m primarily working with legacy code (code without tests) at the moment, and I’ve seen some uses of this interface that took me aback, as for me, the thinking shown below has been with me so long it’s almost a subconscious thought; but I felt the need to say it out loud as it might help someone.

First off, ICloneable is considered a Bad ThingTM; the reason for this is poor naming in relation to whether the clone is a deep or shallow copy, see here for more information about this, but here’s a snippet from BradA’s blog about the use of ICloneable:

Because the interface contract does not specify the type of clone performed, different classes have different implementations. A consumer cannot rely on ICloneable to let them know whether an object is deep-cloned or not.

Having said that, cloning is useful. Given that we’re not going to be able to change the name of the interface method inside the framework, here are my guidelines for working with cloning and the ICloneable interface:

  1. Do use the ICloneable interface .. but decide upfront in your project whether Clone means a deep or shallow copy .. to be perfectly honest a shallow copy is rarely useful, therefore I nearly always stipulate that Clone means deep; and then, be consistent throughout the code-base.
  2. If Clone means shallow in your project, then use the Brad’s guideline and create a new interface, say ICloneable<T>, with two methods: Clone and DeepClone.
  3. If following step 1, implement the Clone method to be type safe and then also provide a public typed version of the call; for example:

public class EffectInfo : ICloneable

    #region ICloneable Members

    // Typed version of the call
   
public EffectInfo Clone() 
    {
        return (EffectInfo)this.MemberwiseClone(); 
    }

    // Interface implementation
   
object ICloneable.Clone()
    {
        return this.Clone();
    }

    #endregion
}

<digression> The ICloneable interface shipped with v.1.0 of the Framework, generics did not yet exist; therefore to implement a type safe version of an interface you have to do interface implementation and then provide public typed versions of the members, as shown above. </digression>

Obviously, if you have the concept of ICloneable<T> in your project, with deep and shallow copies, you do not need to take this approach to get type safe versions of the call.

As usual if you have any comments, questions, flames, enhancements I would love to hear from you. In the meantime think deeply and enjoy.