Weak events in C#, take two

Very poorPoorAverageGoodExcellent (1 votes) 

A few years ago, I blogged about a generic implementation of the weak event pattern in C#. The goal was to mitigate the memory leaks associated with events when you forget to unsubscribe. The implementation was based on the use of weak references to the subscribers, to allow them to be garbage collected.

My initial solution was more a proof of concept than anything else, and had a major performance issue, due to the use of DynamicInvoke every time the event was raised. Over the years, I revisited the weak event problem several times and came up with various solutions, improving a little every time, and I now have an implementation that should be good enough for most use cases. The public API is similar to that of my first solution. Basically, instead of writing an event like this:

public event EventHandler<MyEventArgs> MyEvent;

You write it like this:

private readonly WeakEventSource<MyEventArgs> _myEventSource = new WeakEventSource<MyEventArgs>();
public event EventHandler<MyEventArgs> MyEvent
    add { _myEventSource.Subscribe(value); }
    remove { _myEventSource.Unsubscribe(value); }

From the subscriber’s point of view, this is no different from a normal event, but the subscriber will be eligible to garbage collection if it’s not referenced anywhere else.

The event publisher can raise the event like this:

_myEventSource.Raise(this, e);

There is a small limitation: the signature of the event has to be EventHandler<TEventArgs> (with any TEventArgs you like, of course). It can’t be something like FooEventHandler, or a custom delegate type. I don’t think this is a major issue, because the vast majority of events in the .NET world follow the recommended pattern void (sender, args), and specific delegate types like FooEventHandler actually have the same signature as EventHandler<FooEventArgs>. I initially tried to make a solution that could work with any delegate signature, but it turned out to be too much of a challenge… for now at least Winking smile.


How does it work

This new solution is still based on weak references, but changes the way the target method is called. Rather than using DynamicInvoke, it creates an open-instance delegate for the method when the weak handler is subscribed. What this means is that for an event signature like void EventHandler(object sender, EventArgs e),  it creates a delegate with the signature void OpenEventHandler(object target, object sender, EventArgs e). The extra target parameter represents the instance on which the method is called. To invoke the handler, we just need to get the target from the weak reference, and if it’s still alive,  pass it to the open-instance delegate.

For better performance, this delegate is created only the first time a given handler method is encountered, and is cached for later reuse. This way, if multiple instances of an object subscribe to an event using the same handler method, the delegate is only created the first time, and is reused for subsequent subscribers.

Note that technically, the created delegate is not a “real” open-instance delegate such as those created with Delegate.CreateDelegate. Instead it is created using Linq expressions. The reason is that in a real open-instance delegate, the type of the first parameter must be the type that declares the method, rather than object. Since this information isn’t known statically, I have to dynamically introduce a cast.


You can find the source code on GitHub: WeakEvent. A NuGet package is available here: ThomasLevesque.WeakEvent.

The repository also include code snippets for Visual Studio and ReSharper, to make it easier to write the boilerplate code for a weak event.

A new library to display animated GIFs in XAML apps

Very poorPoorAverageGoodExcellent (6 votes) 

A few years ago, I wrote an article that showed how to display an animated GIF in WPF. The article included the full code, and was quite successful, since WPF had no built-in support for animated GIFs. Based on the issues reported in the comments, I made many edits to the code in the article. At some point I realized it was very impractical, so I published the code on CodePlex (it has now moved to GitHub) under the name WpfAnimatedGif, and started maintaining it there. It was my first serious open-source project, and it was quite popular.

As bug reports started coming in, a serious issue was quickly identified: the library was using a huge amount of memory. There were a few leaks that I fixed, but ultimately the problem was inherent to the way the library worked: it prepared all frames in advance, keeped them in memory, and displayed them in turn using an WPF animation. Having all the frames pre-rendered in memory was reasonable for small images with few frames, but totally impractical for large GIF animations with many frames.

Changing the core of the library to use another approach might have been possible, but there were other issues I wanted to address. For instance, it relied heavily on WPF imaging features, which made it impossible to port it to Windows Phone or Windows Store apps. Also, some parts of the code were quite complex and inefficient, partly because of my initial choice to specify the image as an ImageSource, and changing that would have broken compatibility with previous versions.

WpfAnimatedGif is dead, long live XamlAnimatedGif!

So I decided to restart from scratch to address these issues, and created a new project: XamlAnimatedGif (as you can see, I’m not very imaginative when it comes to names).

On the surface, it seems very similar to WpfAnimatedGif, but at its core it uses a completely different approach. Instead of preparing the frames in advance, they are rendered on the fly using a WriteableBitmap. This approach uses more CPU, but much less RAM. Also, in order to be portable, I couldn’t rely on WPF’s built-in image decoding, so I had to implement a full GIF decoder, including LZW decompression of the pixel data. Matthew Flickinger’s article “What’s In A GIF” was a big help.

The basic usage is roughly the same: just set an attached property on an Image control to specify the GIF animation source.

<Image gif:AnimationBehavior.SourceUri="/images/working.gif" />

Here’s the result in the Windows Phone emulator (yes, it’s a animated GIF representing an animated GIF… I guess it could be called a meta-GIF Winking smile):


Unlike WpfAnimatedGif, the source is specified as an URI or as a stream, rather than an ImageSource. It makes the internal implementation much simpler and more robust.

XamlAnimatedGif currently works on WPF 4.5, Windows 8.1 store apps, and Windows Phone 8.1. It could be extended to support other platforms (WPF 4.0, Windows 8.0, Windows Phone 8.0, Windows Phone Silverlight 8.1, perhaps Silverlight 5), but so far I just focused on making it work on the most recent XAML platforms. I’m not sure if it’s possible to support iOS and Android as well, as I haven’t looked into Xamarin yet. If you want to give it a try, I’ll be glad to accept contributions.

The library is still labeled alpha because it’s new, but it seems reasonably stable so far. You can install it from NuGet:

PM> Install-Package XamlAnimatedGif -Pre 
Posted in Libraries. Tags: , , . 52 Comments »

Easily convert file sizes to human-readable form

Very poorPoorAverageGoodExcellent (No Ratings Yet) 

If you write an application that has anything to do with file management, you will probably need to display the size of the files. But if a file has a size of 123456789 bytes, it doesn’t mean that you should just display this value to the user, because it’s hard to read, and the user usually doesn’t need 1-byte precision. Instead, you will write something like 118 MB.

This should be a no-brainer, but there are actually a number of different ways to display byte sizes… For instance, there are several co-existing conventions for units and prefixes:

  • The SI (International System of Units) convention uses decimal multiples, based on powers of 10: 1 kilobyte is 1000 bytes, 1 megabyte is 1000 kilobytes, etc. The prefixes are the one from the metric system (k, M, G, etc.).
  • The IEC convention uses binary multiples, based on powers of 2: 1 kibibyte is 1024 bytes, 1 mebibyte is 1024 kibibytes, etc. The prefixes are Ki, Mi, Gi etc., to avoid confusion with the metric system.
  • But neither of these conventions is commonly used: the customary convention is to use binary mutiples (1024), but decimal prefixes (K, M, G, etc.).

Depending on the context, you might want to use either of these conventions. I’ve never seen the SI convention used anywhere; some apps (I’ve seen it in VirtualBox for instance) use the IEC convention; most apps and operating systems use the customary convention. You can read this Wikipedia article if you want more details: Binary prefix.

OK, so let’s chose the customary convention for now. Now you have to decide which scale to use: do you want to write 0.11 GB, 118 MB, 120564 KB, or 123456789 B? Typically, the scale is chosen so that the displayed value is between 1 and 1024.

A few more things you might have to consider:

  • Do you want to display integer values, or include a few decimal places?
  • Is there a minimum unit to use (for instance, Windows never uses bytes: a 1 byte file is displayed as 1 KB)?
  • How should the value be rounded?
  • How do you want to format the value?
  • for values less than 1KB, do you want to use the word “bytes”, or just the symbol “B”?

OK, enough of this! What’s your point?

So as you can see, displaying a byte size in human-readable form isn’t as straightforward as you might have expected… I’ve had to write code to do it in a number of apps, and I eventually got tired of doing it again over and over, so I wrote a library that attempts to cover all use cases. I called it HumanBytes, for reasons that should be obvious… It is also available as a NuGet package.

Its usage is quite simple. It’s based on a class named ByteSizeFormatter, which has a few properties to control how the value is rendered:

var formatter = new ByteSizeFormatter
    Convention = ByteSizeConvention.Binary,
    DecimalPlaces = 1,
    NumberFormat = "#,##0.###",
    MinUnit = ByteSizeUnit.Kilobyte,
    MaxUnit = ByteSizeUnit.Gigabyte,
    RoundingRule = ByteSizeRounding.Closest,
    UseFullWordForBytes = true,

var f = new FileInfo("TheFile.jpg");
Console.WriteLine("The size of '{0}' is {1}", f, formatter.Format(f.Length));

In most cases, though, you will just want to use the default settings. You can do that easily with the Bytes extension method:

var f = new FileInfo("TheFile.jpg");
Console.WriteLine("The size of '{0}' is {1}", f, f.Length.Bytes());

This method returns an instance of the ByteSize structure, whose ToString method formats the value using the default formatter. You can change the default formatter settings globally through the ByteSizeFormatter.Default static property.

A note on localization

Not all languages use the same symbol for “byte”, and obviously the word “byte” itself is different across languages. Currently the library only supports English and French; if you want your language to be supported as well, please fork, add your translation, and make a pull request. There are only 3 terms to translate, so it shouldn’t take long Winking smile.

Posted in Libraries. Tags: , , . No Comments »

StringTemplate: another approach to string interpolation

Very poorPoorAverageGoodExcellent (No Ratings Yet) 

With the upcoming version 6 of C#, there’s a lot of talk on CodePlex and elsewhere about string interpolation. Not very surprising, since it’s one of the major features of that release… In case you were living under a rock during the last few months and you haven’t heard about it, string interpolation is a way to insert C# expressions inside a string, so that they’re evaluated at runtime and replaced with their values. Basically, you write something like this:

string text = $"{p.Name} was born on {p.DateOfBirth:D}";

And the compiler transforms it to this:

string text = String.Format("{0} was born on {1:D}", p.Name, p.DateOfBirth);

Note: the syntax shown above is the one from the latest design notes about this feature. It might still change before the final release, and the current preview build of VS2015 uses a different syntax: “\{p.Name} was born on \{p.DateOfBirth:D}”.

I really love this feature. It’s going to be extremely convenient for things like logging, generating URLs or queries, etc. I will probably use it a lot, especially since Microsoft has listened to community feedback and included a way to customize how the embedded expressions are evaluated (see the part about IFormattable in the design notes).

But there’s one thing that bothers me, though: since interpolated strings are interpreted by the compiler, they have to be hard-coded ; you can’t extract them to resources for localization. This means that this feature cannot be used for localization, and we’re stuck with old-fashioned numeric placeholders in localized strings.

Or are we really?

For a few years now, I’ve been using a custom string interpolation engine that can be used like String.Format, but with named placeholders instead of numeric ones. It takes a format string, and an object with properties that match the placeholder names:

string text = StringTemplate.Format("{Name} was born on {DateOfBirth:D}", new { p.Name, p.DateOfBirth });

Obviously, if you already have an object with the properties you want to include in the string, you can just pass that object directly:

string text = StringTemplate.Format("{Name} was born on {DateOfBirth:D}", p);

The result is exactly what you would expect: the placeholders are replaced with the values of the corresponding properties.

In which ways is it better than String.Format?

  • It’s much more readable: a named placeholder tells you immediately which value will go there
  • It’s less error-prone: you don’t need to pay attention to the order of the values to be formatted
  • When you extract the format strings to resources for localization, the translator sees a name in the placeholder, not a number. This gives more context to the string, and makes it easier to understand what the final string will look like.

Note that you can use the same format specifiers as in String.Format. The StringTemplate class parses your format string into one compatible with String.Format, extracts the property values into an array, and calls String.Format.

Of course, parsing the string and extracting the property values with reflection every time would be very inefficient, so there are a some optimizations:

  • each distinct format string is only parsed once, and the result of the parsing is added to a cache, to be reused every time.
  • for each property used in a format string, a getter delegate is generated and cached, to avoid using reflection every time.

This means that the first time you use a given format string, there will be the overhead of parsing and generating the delegates, but subsequent usages of the same format string will be much faster.

The StringTemplate class is part of a library called NString, which also contains a few extension methods to make string manipulations easier. The library is a PCL that can be used with all .NET flavors except Silverlight 5. A NuGet package is available here.

[WPF] Declare global hotkeys in XAML with NHotkey

Very poorPoorAverageGoodExcellent (2 votes) 

A common requirement for desktop applications is to handle system-wide hotkeys, in order to intercept keyboard shortcuts even when they don’t have focus. Unfortunately, there is no built-in feature in the .NET framework to do it.

Of course, this is not a new issue, and there are quite a few open-source libraries that address it (e.g. VirtualInput). Most of them rely on a global system hook, which allow them to intercept all keystrokes, even the ones you’re not interested in. I used some of those libraries before, but I’m not really happy with them:

  • they’re often tied to a specific UI framework (usually Windows Forms), which makes them a bit awkward to use in another UI framework (like WPF)
  • I don’t really like the approach of intercepting all keystrokes. It usually means that you end up with a big method with lots of if/else if to decide what to do based on which keys were pressed.

A better option, in my opinion, is to listen only to the keys you’re interested in, and declare what to do for each of those. The approach used in WPF for key bindings is quite elegant:

    <KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}" />
    <KeyBinding Gesture="Ctrl+Alt+Subtract" Command="{Binding DecrementCommand}" />

But of course, key bindings are not global, they require that your app has focus… What if we could change that?

NHotkey is a very simple hotkey library that enables global key bindings. All you have to do is set an attached property to true on your key bindings:

    <KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}"
                HotkeyManager.RegisterGlobalHotkey="True" />
    <KeyBinding Gesture="Ctrl+Alt+Subtract" Command="{Binding DecrementCommand}"
                HotkeyManager.RegisterGlobalHotkey="True" />

And that’s it; the commands defined in the key bindings will now be invoked even if your app doesn’t have focus!

You can also use NHotkey from code:

HotkeyManager.Current.AddOrReplace("Increment", Key.Add, ModifierKeys.Control | ModifierKeys.Alt, OnIncrement);
HotkeyManager.Current.AddOrReplace("Decrement", Key.Subtract, ModifierKeys.Control | ModifierKeys.Alt, OnDecrement);

The library takes advantage of the RegisterHotkey function. Because it also supports Windows Forms, it is split into 3 parts, so that you don’t need to reference the WinForms assembly from a WPF app or vice versa:

  • The core library, which handles the hotkey registration itself, independently of any specific UI framework. This library is not directly usable, but is used by the other two.
  • The WinForms-specific API, which uses the Keys enumeration from System.Windows.Forms
  • The WPF-specific API, which uses the Key and ModifierKeys enumerations from System.Windows.Input, and supports global key bindings in XAML.

If you install the library from Nuget, add either the NHotkey.Wpf or the NHotkey.WindowsForms package; the core package will be added automatically.