Saturday 24 March 2012

Live Tiles revisited

Back in December, I wrote about dynamically generating live tiles on the phone from a xaml template.  I released first live tiles application Terminator which shows sunrise and sunset around the world using NASA blue marble imagery.  Some of our customers asked for sunrise and sunset times, and where better than on a live tile.

However, occasionally the tile would not update correctly using code based on that I showed back in December. 

The symptoms were odd.  The layout was all over the place, and as I started changing things, I found that things were about to get even more peculiar.

Originally, the tile was defined as a user control with a defined height and width of 173 pixels, containing a grid with some auto resize columns.  So, I simplified my control to use a canvas as follows:

<Canvas Background="Red" >
<Image Canvas.Left="0" Canvas.Top="27"
Width="173" Height="89" x:Name="imgSunrise"
Source="/images/lowsunrise.png"/>

<TextBlock Canvas.Left="12" TextAlignment="Right"
Width="149" Text="{Binding SunriseTime}"/>
<TextBlock Canvas.Left="12">Sunrise</TextBlock>
<TextBlock Canvas.Left="12" Canvas.Top="27" TextAlignment="Right"
Width="149" Text="{Binding SunsetTime}"/>
<TextBlock Canvas.Left="12" Canvas.Top="27" >Sunset</TextBlock>
<TextBlock Canvas.Left="12" Canvas.Top="112"
Width="149" TextWrapping="Wrap" Text="{Binding Location}" />
</Canvas>

Previously, my control was rendering on a transparent background so that it would match the theme the user had selected, but I thought I’d try it with a fixed background so I could see what was happening.


What I found was that occasionally, my color was not being applied to my canvas, and it was still showing through with the theme color.


That discovery led me to believe that the layout had not yet completed.


Now, as was described back in December, the behavior of the notifications changes based on where they are run.  In the user agent, the load happens immediately, when the tile is used on a panel, it gets run multiple times.


My original strategy was to handle the change when the first LayoutUpdated event was fired, however, to my surprise, calling _fe.Arrange(layoutRect); where _fe is the framework element we’re trying to lay out, only generates a single call to LayoutUpdated in some circumstances, partcularly after the app has been Tombstoned.


In addition, it transpired that the values of ActualHeight and ActualWidth in this case were both 0.  I guess it’s no surprise that it rendered incorrectly in that case!  What appeared to have happened was that the image was way to big, and grainy.  Eventually I downloaded from Isolated storage, and found this is what was actually produced:


sunrise


One of the interesting things to note about this image is that it is not square, certainly not 173x173 like a tile should be, despite that being the size requested.


In fact it’s 173x135.  So, when rendering a tile, it turns out that metro will stretch the smallest dimension to 173, which explained the odd look described earlier.


So, what did I do to fix it? 


I tried subscribing to the SizeChanged event.  That didn’t work:  In fact it never fired. 


I tried setting up a DispatcherTimer, and handling it in 500msec, but that didn’t make any difference either.


Eventually I found a horrible hack that worked, though I don’t know why:


I did this in a loop (don’t try this at home, kids):



for (int i = 0; i < 3; i++)
{

_fe.Measure(new Size(173, 173));
_fe.Arrange(layoutRect);
_fe.UpdateLayout();

if (!bSynchronous || _fe.ActualHeight == 173) break;
// we do this in a loop because sometimes it doesn't work!
}




This code, surprisingly did work, though all Measure/Arrange/UpdateLayout were all required.  Initiallly I started with just Arrange.


But, in playing with this code to write the blog, I found an even simpler solution.  Set the size on the Canvas in the first place, and the problem seems to disappear (that is to say, the way that I used to be able to break it doesn’t break it any more).


This all begs the question:  microsoft, Why is this so hard?


That’s about 12 hours more of my life wasted.  The whole implementation of Silverlight/.NET is in a black box, where we can’t see the code, particularly on the phone where we can’t easily disassemble the source.  Even then it quickly drops down into native code, becoming inaccessible again.


Back in the old days of C++/MFC, it was at least possible to see what the source code was doing, and figure it out.  Now we just have to guess.  It’s turned programming into a giant game, where you need to figure out that right move to proceed, and that’s incredibly frustrating.


It all comes down to a lack of documentation about what actually is going on.  The trouble with blogs like these and all the other search engine led development, is we’re documenting workarounds for current implementations.  There’s no contract that says this behaviour will stay the same, so the next update may break your programs.


If you found this useful, and it saves you any time please consider purchasing one of our apps.  I have to admit, at the moment, sales are terrible for windows phone apps, and if things don’t improve soon, I won’t be wasting any more time developing new phone apps.  I make more money off my 2kW solar panels in a day than I do from phone apps in a month.  And, WM6.5 apps are still bringing in as much money per month as WP7 ones do.

Wednesday 21 March 2012

Refactoring your way into a non-working program

Today I was tracking down a bug for a client, and eventually tracked it down to a virtual function call that was not being called.

It took a while to figure out.  First, I’d split my data class into itself and a base class, and I’d split my object performing the work into itself and a base class as well, ending up with the following classes:

class DataBaseClass
{
//...
};

class DataClass : class DataBaseClass
{
//...
};

class ObjectBaseClass
{
// ...
virtual void virt_func(DataBaseClass *pObj);
};

class ObjectClass
{
//...
virtual void virt_func(DataClass *pObj);
}


After discovering which class wasn’t having it’s virt_func called, it became obvious:  The signatures don’t match.  But how can I get the compiler to find these for me, that’s the important question.


I was going to blog about how C# is superior to C++ in this regard, until I discovered that VC++2010 actually supports the override keyword, so to catch the error, simply add the keyword override to the end of the derived virt_func’s as follows.  Alas it’s a non-standard extension, which requires a pragma to get rid of the warnings.


// disable warnings about override
#pragma warning(push)
#pragma warning(disable: 4481)

class ObjectClass
{
//...
virtual void virt_func(DataClass *pObj) override;
}

// ...
#pragma warning(pop)



This now generates an error when compiled, and points out all the places I got it wrong, and will continue to do so if I refactor again!

Tuesday 20 March 2012

ShellExecute print verb fails on WOW64

I have a 32 bit program that has been installed by a customer on 64 bit windows.

There appears to be a problem with using ShellExecute and the print verb in that configuration.  First my test program.

// printme.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "objbase.h"
#include <windows.h>

#include <shellapi.h>

int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Usage: %s file_to_print", argv[0]);
return 0;
}

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) ; //| COINIT_DISABLE_OLE1DDE);

HINSTANCE retVal = ::ShellExecute(NULL, "print", argv[1], NULL, NULL, 0); // don't ask, as the user can always cancel...
printf("RetVal = %08x\n", retVal);
printf("LastError = %08x\n", GetLastError());
return 0;
}


This program works correctly on 32 bit windows version up to Windows 7.  The program simply runs the print verb on the first argument passed on the command line.


printme Page1.htm


On the system in question, the registry is set up as follows:


regprint64



If I run the following command
rundll32 c:\windows\system32\mshtml.dll,PrintHTML “Page1.htm”
the print dialog is successfully shown.


However running my program blinks, but nothing ever launches.


Process manager shows the following:
failure


As you can see the selected bottom line is running the 32bit version, which never completes.  The 64 bit version run previously does work.


Is there any workaround?  Not that I’ve found yet.

Friday 16 March 2012

My splash screen closed my message box

Today, while trying to debug on a very slow virtual machine, I decided to add a splash screen to my WPF application.  After all, my phone applications have one, so how hard could it be?

First I found these instructions on MSDN for adding a splash screen

Wow.  That’s easy!  However to my surprise, I found that in some circumstances, my application caused a message box to show before the main window was displayed, as my MessageBox was shown by the constructor.

And to my surprise, the splash screen closed that message box.  Now I’m not the first to find this problem.  There are various discussions and links here, but I have to admit, I didn’t really like any of the three options presented there.

So, I thought, there must be a better way.  Well, I think I’ve found one!

First, construct your SplashScreen object as shown in this constructor:

MainWindow()
{
SplashScreen ss = new SplashScreen("Images/splash.png");

// show the splash screen
ss.Show(false);

// do the rest of the constructor work.
// ...
//

ss.Close(new Timespan.FromSeconds(0.1));
}

 

When I first wrote the above, I had my splash screen flicker, as my main application appeared on top of the splash screen.  To solve that I came up with a very confusing BeginInvoke, which is only necessary to solve a different problem.

 

Turns out, that because I followed the initial instructions, I had added my splash screen with a build action of “SplashScreen”.  That’s wrong.  The build action should be resource if you want to do it manually, otherwise, it appears that you end up with two splash screens!


Wednesday 14 March 2012

WPF program crashes when printing

I had a customer this week let me know that he was unable to print from our Payslips for HMRC PAYE Tools program.

After a long time spent debugging, it transpires that the computer had a problem in the registry, where a font was incorrectly installed.

In his case, it was this font: MT Extra (TrueType)
and it was installed here on his XP machine:
C:\Program Files\Common Files\Microsoft Shared\Equation\mtextra.ttf

We deleted the entry, and managed to print to the XPS driver, but printing to the printer itself still didn’t work.  Maybe it requires a reboot?  Still looking into that one.

And we’re not the first to see this either.  Here are a couple more reports in the wild:

Bradley Grainger's 2009 blog entry

and this one from 2011 by Divya N Singh

Friday 9 March 2012

Getting an integer identity for an object on WP7

Today’s quirk was discovered while trying to get an object’s identity.

Jeffrey Richter in CLR via C# (version 2)mentions that you can call RuntimeHelpers static GetHashCode method in a box at the bottom of page 148 to get a unique ID for an object.

The documentation for the .NET framework 4 and earlier all say this about GetHashCode:

The RuntimeHelpers.GetHashCode method always calls the Object.GetHashCode method non-virtually, even if the object's type has overridden the Object.GetHashCode method. Therefore, using RuntimeHelpers.GetHashCode differs from calling GetHashCode directly on the object with the Object.GetHashCode method.

But, if you change to the Silverlight version of the documentation of GetHashCode that statement is missing, and if you actually build the code you’ll find that it just calls GetHashCode on the object itself, with whatever override is provided on that type (as these people found out)

Further investigation into GetHashCode all the way back to V2 of the framework looks unpromising as well:

The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.

There is some information here on other possible strategies on stackoverflow for getting an identity.

My intended use was for serialization, and the above thread points out the ObjectIDGenerator class which looks like exactly the functionality I’m looking for, but it doesn’t work on Silverlight!

GCHandle also doesn’t look like it will do the job, as most members are security critical, and the only value it gives out is a pinned address anyway, though there is a promising Narrowing operator, so casting to an IntPtr looks like it might work.

However, when I try to run it I get an exception:

Attempt to access the method failed: System.Runtime.InteropServices.GCHandle.set_Target(System.Object)

which I guess is expected as they’re marked with [SecurityCritical] attributes.

Despite all that, it does appear that object.ReferenceEquals will tell me if two objects are the same, and a promising approach appears to be

Dictionary<object, int> dict = new Dictionary<object, int>(10);

I initially created two objects and added them, and when querying dict.Count I got two items.

 

So, on my objects I created, I added an override of object.Equals to always return true.

Disappointingly, I now only have one object in my dictionary, as it obviously uses equality rather than identity.

 

However, hidden among all of the dictionary constructors is a constructor that takes an IEqualityComparer<T>, if only I could figure out how to create one.

 

Luckily, there’s an implementation here, the only change i made was to remove the call to RuntimeHelpers.GetHashCode() and use obj.GetHashCode() instead, as they do the same thing anyway on the phone.

 

After that, even with my operator= and GetHashCode overridden in my class to always return true and 0 respectively, my code as follows successfully labels two unique objects  in its Dictionary.

var datesTmp = new EphemeralState();
Dictionary<object, int> dict =
new Dictionary<object, int>
(10, ObjectReferenceEqualityComparerer<object>.Default);

dict[datesTmp] = 1;

var datesTmp2 = new EphemeralState();
dict[datesTmp2] = 2;

Debug.WriteLine(dict.Count);


 

So now we know how to build something equivalent to the ObjectIDGenerator class.  Find the value of an object key in the dictionary above, and if it doesn’t exist, generate a new id, and add it to the dictionary.

 

Back to work now.


 

Thursday 8 March 2012

How to monitor garbage collections in a WP7 app

I’m currently working on an app that has the potential to use lots of memory, and I’d like to cache the results as much as I can to speed things up for the user.

I’d also like to get my app certified and available for sale, so must be careful not to eat up all the memory.  One way to do that is with a WeakReference object, but I found that my objects were being garbage collected at the first opportunity, which didn’t really help.

I thought about doing an ephemeral garbage collection by calling GC.Collect(0) on the phone, but that isn’t allowed, and throws an exception.

What I really needed to do was keep my objects alive for a little while after they were used, but I really want to define a little while in terms of the number of garbage collections, rather than running a timer to continually dispose objects.

Unfortunately, I discovered there wasn’t any obvious event raised when a garbage collection is fired, but a little lateral thinking let me realize that there is an event that is called, thought it’s not marked as an event.

It’s actually every object’s finalizer!

So my strategy is to create an object, to which I hold only a weak reference, and when it’s garbage collected I update my statistics, and perform whatever other GC related actions I need to on the UI thread.

To save anyone else the pain, I include the code below.  To fire it up, just reference GCWatcher.GCINFO somewhere in your application, and the notifications begin.

public class GCWatcher
{
/// <summary>
/// static constructor collects the total memory on the device
/// </summary>
static GCWatcher()
{
TotalMemory = (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory");
}

/// <summary>
/// Store a weak reference to our current sacrificial garbage collector object
/// </summary>
static WeakReference _activeGC;

/// <summary>
/// keep a count of the total number of garbage collections seen
/// </summary>
static int gcCount = 0;

/// <summary>
/// store the total memory found on the device
/// </summary>
public static readonly long TotalMemory;

/// <summary>
/// This placeholder should be modified to raise whatever notifications you need in your application
/// It will always be called on the main thread.
/// </summary>
static void Notify()
{
// placeholder for our notification call
}

/// <summary>
/// Property to get the current Garbage Collection info object. If one does not exist it will be created.
/// </summary>
static public GCWatcher GCINFO
{
get
{
WeakReference currentwr = Interlocked.CompareExchange(ref _activeGC, null, null);
GCWatcher current = currentwr == null ? null : currentwr.Target as GCWatcher;
if (current == null)
{
current = new GCWatcher();
Interlocked.Exchange(ref _activeGC, new WeakReference(current));
}
return current;
}
}

/// <summary>
/// Instance property to return the memory usage at the most recent garbage collection
/// </summary>
public long ApplicationCurrentMemoryUsage
{
get;
set;
}

/// <summary>
/// Instance property to return the peak memory usage at the most recent garbage collection
/// </summary>
public long ApplicationPeakMemoryUsage
{
get;
set;
}

/// <summary>
/// protected constructor, to create a new GCWatcher object, and initialize the properties.
/// This is always called on the UI thread.
/// </summary>
internal GCWatcher()
{
// when we create a GC Watcher, we collect the statistics
ApplicationCurrentMemoryUsage = (long) DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
ApplicationPeakMemoryUsage = (long) DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");

}

/// <summary>
/// implement a finalizer, that keeps track of our garbage collections via the weak referened object
/// </summary>

~GCWatcher()
{
Interlocked.Exchange(ref _activeGC, null); // zap the value, as we're destroyed
Interlocked.Increment(ref gcCount);

Deployment.Current.Dispatcher.BeginInvoke(
// create a new GCWatcher on the main thread.
() =>
{
WeakReference tmp = new WeakReference(new GCWatcher());
Interlocked.Exchange(ref _activeGC, tmp);
GCWatcher.Notify();
});
}

/// <summary>
/// Thread safe property to return the total counts of garbage collections
/// </summary>
int Count
{
get
{
return Interlocked.CompareExchange(ref gcCount, 0, 0);
}
}

Wednesday 7 March 2012

Thread Safety on WPF, Silverlight and WP7

About a week ago I posted about IsolatedStorage and Thread Safety and what exactly the statement Any instance members are not guaranteed to be thread safe means in the documentation of the class libraries.

A lot of discussion making superstitious claims about serializing access to instance members ensued, however all of those led to illogical conclusions, implying that it was never possible to write a program that used multiple threads.

Eventually, I contacted members of the Base Class Library team who responded with the following definitive statements:

In general, the overall Framework guidance should apply to IsolatedStorage as well.

- Static members should be thread safe.

- Instance members cannot be expected to be thread safe unless otherwise specified.

- Instance members on different instances should be safe to use concurrently.

In addition, specifically related to IsolatedStorage, I got this definitive statement:

If you work on distinct instances of IsolatedStorage / ..File / ..Stream on different threads you will not run into any concurrency issues.

Different instances of those types have private copies of all internal data; and in cases where we need to update global state (e.g. isolated storage quota) we do all the necessary locking for you.

Note, however, that if you open two distinct Stream instances on the same file – whether through the iso storage or directly thought FileStream, we do not make any guarantees about the order in which these instances will access the underlying physical file. When using two distinct stream instances on the same file concurrently from different threads, you may end up with interleaved, mixed or invalid data in the file. However, the stream objects themselves will remain consistent and valid.

This is different from using one single Stream object from different threads: That is not supported and can break the stream object itself, not only resulting in data corruption, but also in weird runtime behaviour.

So there you have it.  Put your mutexes and locks down and step away from the code face and think!

If you are seeing what looks like a threading problem, and you found a mutex or lock solved it, it probably has, but not for the reason you thought.  There is probably some other multithreading logic error you had not foreseen, and your lock will either kill performance, or just make the bug even harder to find.

Thursday 1 March 2012

WP7 Bing Maps Crash while being led down the garden path!

There I was, innocently trying to data bind to my collection of objects, and use an item template to render them on my maps control for an upcoming application.

So, I added a layer to my map like this:

<my:MapItemsControl x:Name="tracksLayer"
ItemsSource="{Binding Tracks }"
ItemTemplate="{StaticResource TrackTemplate}" />



and implemented my data template like this in the page resources:


<SolidColorBrush x:Key="FadedBrush" Color="Blue" Opacity=".5" />

<DataTemplate x:Name="TrackTemplate">
<MapPolyline Locations="{Binding Locations}"
Stroke="{StaticResource FadedBrush}"
StrokeThickness="5" />
</DataTemplate>



That all worked fine, and I got my brush displayed.


So, I thought great, now lets ask the track what color it should be, and changed the stroke definition to look like this:


<DataTemplate x:Name="TrackTemplate">
<my:MapPolyline Locations="{Binding Locations}"
Stroke="{Binding TrackBrush}"
StrokeThickness="5" />
</DataTemplate>



To my surprise, this threw an exception (or two) and terminated the program.


After a couple hours of debugging to figure out what had happened and being led down the garden path by the StaticResource, I eventually came across the fact that Stroke and StrokeThickness are not dependency properties in MapShapeBase.


Luckily, someone else had solved the problem here.  But be careful, the declarations there aren’t marked public and the dependency properties are implemented differently in WPF, so it won’t work out of the box.


I’ve attached my class here updated for WP7:


public class MapPolylineBindable : MapPolyline
{
public static readonly DependencyProperty StrokeProperty;
public static readonly DependencyProperty StrokeThicknessProperty;

static MapPolylineBindable()
{
MapPolylineBindable.StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(MapPolylineBindable),
new PropertyMetadata(null, OnStrokeExChanged));

MapPolylineBindable.StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(MapPolylineBindable),
new PropertyMetadata(1.0, OnStrokeThicknessExChanged));
}

public new Brush Stroke
{
get { return (Brush)GetValue(MapPolylineBindable.StrokeProperty); }
set { SetValue(MapPolylineBindable.StrokeProperty, value); }
}

private static void OnStrokeExChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
(o as MapPolyline).Stroke = (Brush)e.NewValue;
}

public new double StrokeThickness
{
get { return (double)GetValue(MapPolylineBindable.StrokeThicknessProperty); }
set { SetValue(MapPolylineBindable.StrokeThicknessProperty, value); }
}

private static void OnStrokeThicknessExChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
(o as MapPolyline).StrokeThickness = (double)e.NewValue;
}
}

and to bind, you need to do this:

 


<DataTemplate x:Name="TrackTemplate">
<hack:MapPolylineBindable Locations="{Binding Locations}"
Stroke="{Binding TrackBrush}"
StrokeThickness="5" />
</DataTemplate>