Archive for the ‘Debugging’ Category

PropertyDescriptor AddValueChanged Alternative

April 7, 2008

I’ve been meaning to write about this for a while since I’ve seen this approach mentioned lots of times on the newsgroups but have seen no mentions about the caveats. Just today I saw the same problem in some code from one of the disciples. The scenario is that you want to know when the value of a dependency property changes but you don’t have a one to one relationship with the object. For example, you have a list of items and you want to know when the IsSelected property of an item has changed.

The solution that I have seen given for this is to get to the PropertyDescriptor and use its AddValueChanged method to provide an EventHandler to receive a notification when the property has changed. Sometimes, the reply will mention/use DependencyPropertyDescriptor directly but its the same thing since that is just a derived PropertyDescriptor that provides additional information about the underlying DependencyProperty it represents. You  can get to this property descriptor in a few ways but the most common are to get it from the TypeDescriptor.GetProperties method or using the DependencyPropertyDescriptor.FromProperty.

The issue with this approach is that it will root your object so it will never get collected by the GC. There have been plenty of discussions about how hooking events (particularly static events) can root your object so I won’t go into great detail there. While it does not seem that you are hooking a static event in this case, in essence you are. When you add a handler to a property descriptor, that property descriptor stores the delegate in a hashtable keyed by the object whose property you are hooking. A delegate/handler is basically a pointer to a method on an object (or no object if its for a static method) so that means the property descriptor has a reference to your object as well as the object whose value you are watching (since that is the key into the hashtable). The property descriptors themselves are cached statically so the hashtable is kept around and therefore your object and the one you are watching are as well.

I personally like to use the Scitech memory profiler (or you can use the Microsoft CLR Profiler) when debugging memory leak issues but you can see the issue manifest itself pretty easily in this case. First we’ll do a benchmark to make sure that we can check whether the object was collected.

ListBoxItem i = new ListBoxItem();
WeakReference wr = new WeakReference(i);
i = null;
GC.Collect();
bool isAlive = wr.IsAlive;

If you run this code and check isAlive, you will see that it returns false indicating that the ListBoxItem was not referenced and was able to be collected. Now let’s try using the AddValueChanged method.

ListBoxItem i = new ListBoxItem();
WeakReference wr = new WeakReference(i);
PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(ListBoxItem))["IsSelected"];
// the following yields the same pd
//PropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ListBoxItem.IsSelectedProperty, typeof(ListBoxItem));
prop.AddValueChanged(i, new EventHandler(this.OnValueChanged));
i = null;
GC.Collect();
bool isAlive = wr.IsAlive;

This time isAlive returns true because the property descriptor is maintaining a reference to the ListBoxItem. Now, let’s try an alternative approach that involves creating a helper class to listen for the property change.

ListBoxItem i = new ListBoxItem();
WeakReference wr = new WeakReference(i);
PropertyChangeNotifier notifier = new PropertyChangeNotifier(i, “IsSelected”);
notifier.ValueChanged += new EventHandler(OnValueChanged);
i = null;
GC.Collect();
bool isAlive = wr.IsAlive;

In this case isAlive is false indicating that the object can be collected even though we’re still maintaining an explicit reference to the notifier. The implementation for the class – PropertyChangeNotifier – is listed below. The class is basically a simple DependencyObject that exposes 2 properties – Value returns the value of the property of the object that it is watching and PropertySource returns the object whose property it is watching. The constructor for the object takes the object whose property is to be watched for changes and the property that should be watched. This class takes advantage of the fact that bindings use weak references to manage associations so the class will not root the object who property changes it is watching. It also uses a WeakReference to maintain a reference to the object whose property it is watching without rooting that object. In this way, you can maintain a collection of these objects so that you can unhook the property change later without worrying about that collection rooting the object whose values you are watching.

public sealed class PropertyChangeNotifier :
DependencyObject,
IDisposable
{
#region Member Variables
private WeakReference _propertySource;
#endregion // Member Variables
 
#region Constructor
public PropertyChangeNotifier(DependencyObject propertySource, string path)
: this(propertySource, new PropertyPath(path))
{
}
public PropertyChangeNotifier(DependencyObject propertySource, DependencyProperty property)
: this(propertySource, new PropertyPath(property))
{
}
public PropertyChangeNotifier(DependencyObject propertySource, PropertyPath property)
{
if (null == propertySource)
throw new ArgumentNullException(“propertySource”);
if (null == property)
throw new ArgumentNullException(“property”);
this._propertySource = new WeakReference(propertySource);
Binding binding = new Binding();
binding.Path = property;
binding.Mode = BindingMode.OneWay;
binding.Source = propertySource;
BindingOperations.SetBinding(this, ValueProperty, binding);
}
#endregion // Constructor
 
#region PropertySource
public DependencyObject PropertySource
{
get 
{
try
{
// note, it is possible that accessing the target property
// will result in an exception so i’ve wrapped this check
// in a try catch
return this._propertySource.IsAlive
? this._propertySource.Target as DependencyObject
: null;
}
catch
{
return null;
}
}
}
#endregion // PropertySource
 
#region Value
/// <summary>
/// Identifies the <see cref=”Value”/> dependency property
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(“Value”,
typeof(object), typeof(PropertyChangeNotifier), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged)));
 
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PropertyChangeNotifier notifier = (PropertyChangeNotifier)d;
if (null != notifier.ValueChanged)
notifier.ValueChanged(notifier, EventArgs.Empty);
}
 
/// <summary>
/// Returns/sets the value of the property
/// </summary>
/// <seealso cref=”ValueProperty”/>
[Description("Returns/sets the value of the property")]
[Category("Behavior")]
[Bindable(true)]
public object Value
{
get
{
return (object)this.GetValue(PropertyChangeNotifier.ValueProperty);
}
set
{
this.SetValue(PropertyChangeNotifier.ValueProperty, value);
}
}
#endregion //Value
 
#region Events
public event EventHandler ValueChanged;
#endregion // Events
 
#region IDisposable Members
public void Dispose()
{
BindingOperations.ClearBinding(this, ValueProperty);
}
#endregion
}

Another possible approach would be to implement your own derived WeakEventManager but I’ll leave that as an exercise for the reader. For those that choose to go this route, there is such a class – except its internal – in the PresentationFramework assembly.

SyncHashtable is not enumerable…

January 19, 2008

One of the things I really like about working on Mole is that I get to debug some obscure issues that I haven’t come across before. Today, Karl mentioned that there was an issue when dealing with collections – specifically with a synchronized hashtable. Mole was dealing with collections using one of the base collection interfaces – ICollection. He fixed the issue correctly by iterating the IDictionaryEnumerator you get from the IDictionary implementations of a hashtable but I wanted to see what was go on so I decided to look into this further.

The problem can be reproduced with the following snippet:

Hashtable ht = new Hashtable();

Hashtable syncedTable = Hashtable.Synchronized(ht);

IEnumerator enumerator = ((ICollection)syncedTable).GetEnumerator();

Or more likely it would be something like this:

Hashtable ht = new Hashtable();

Hashtable syncedTable = Hashtable.Synchronized(ht);

syncedTable.Add(“Foo”, “Bar”);

EnumerateCollection(syncedTable);

Where EnumerateCollection was something like the following:

private void EnumerateCollection(IEnumerable enumerable)

{

    foreach (object value in enumerable)

    {

        // do something

    }

}

I took at a look at MS’ code for the Hashtable class using Reflector and there is an obvious bug in their implementation. I did a quick internet search and it seems like people have been bitten by this same issue for a while so its hard to believe that it still exists within the framework today. In case anyone encounters the issue, I’ll explain what’s going on.

Hashtable implements the IDictionary interface which derives from ICollection and therefore IEnumerable. Both IDictionary and IEnumerable define a GetEnumerator method. For IDictionary this returns an IDictionaryEnumerator and for IEnumerable this returns an IEnumerator. Hashtable’s implementation of the IDictionary method is a public virtual GetEnumerator method. Its implementation of the IEnumerable method is an explicit implementation of the interface method.

e.g. IEnumerator IEnumerable.GetEnumerator();

The Hashtable class exposes a public static method named Synchronize that is supposed to take a hashtable and return a thread safe hashtable. There are actually flaws in the thread safety aspect of the implementation but that is another matter outside the issue we were dealing with. The Synchronize methods returns an instance of a private nested class named SyncHashtable which derives from Hashtable and is basically a thin wrapper around the Hashtable you pass to the Synchronize method. SyncHashtable overrides the virtual methods on the base Hashtable class and attempts to make dealing with the hashtable thread safe by using locks around edits.

SyncHashtable correctly overrides the public virtual GetEnumerator method and returns the IDictionaryEnumerator of the hashtable its wrapping. However, and herein lies the problem, it does not reimplement the IEnumerable.GetEnumerator method. Therefore, you get the base Hashtable’s implementation which returns an enumerator (HashtableEnumerator) for the SyncHashtable itself. This enumerator class assumes that the buckets member variable of the Hashtable it is to enumerate is non-null but the SyncHashtable specifically uses an overload of the Hashtable constructor that does not initialize this member (and others normally initialized for a Hashtable). It makes sense that they would not want to initialize these values since the SyncHashtable doesn’t store its own values – remember its just a thin wrapper around the Hashtable you provided to the Synchronize method – but then they should have reimplemented the IEnumerable.GetEnumerator method.

So if you’re writing any code that enumerates collections using the IEnumerable interface (directly or indirectly) with an object where you’re not in control of the source, you may want to consider dealing with the IDictionary’s enumerator first.

So you could fix the EnumeratorCollection method above as follows:

private void EnumerateCollection(IEnumerable enumerable)

{

    IEnumerator enumerator;

 

    // SyncHashtable has a bug where its IEnumerable

    // returns an enumerator whose ctor causes a crash.

    // instead, we can get around the problem using its 

    // IDictionary.GetEnumerator impl

    Hashtable table = enumerable as Hashtable;

 

    if (null != table)

        enumerator = table.GetEnumerator();

    else

        enumerator = enumerable.GetEnumerator();

 

    while (enumerator.MoveNext())

    {

        object value = enumerator.Current;

 

        // do something

    }

}

Compare Property & Field Values with Mole

January 15, 2008

As seems to happen with Mole, a suggestion quickly snowballed into a feature implementation. Mole now has the ability to save the members (properties/fields) of the selected element to an xml file and allow you to load that xml file back in to allow property comparison. This will be extremely helpful when you’re trying to debug a problem where something works for one element but doesn’t for another instance. There’s even an option to filter out members with the same value so you can see just the properties that differ.

 You can download the latest version here.

In addition, Karl has been posting some videos on YouTube that show how to use Mole. You can view those videos here.

Editing Properties and Fields with Mole

January 1, 2008

When debugging there are often times when you need to manipulate the value of a property or field within the watch window. Mole is a great visualizer that lets inspect the properties/fields of other objects in the visual/logical tree but if you saw something that needed to be changed, you would have to come out of the visualizer, change the value (assuming you could easily write the code necessary in the watch window Name column to locate the appropriate object) and then continue debugging.

Well, one of the things that I really wanted to see in Mole was editing capability similar to that of Snoop so we took the time and added it in. I wrote the editing infrastructure making use of .NET’s TypeConverters and Karl wrote the editors making it easy to edit common data types like fonts, colors, enums, etc. You can check it out here.

Note, there are some limitations to what can be done. For example, you can’t create new instances of classes as you might be able to do with the watch window. Since we’re using typeconverters, the editing is limited to the typeconverter associated with the property/field type. Maybe this is something we can look to add in a future version.

Mole for Visual Studio

December 15, 2007

Karl is at it again. He extended Mole to allow it to be used for other types of objects including WinForms Controls, ASP.Net controls, etc. You can read about it on Mole’s home page or on codeproject.

Karl is very kind in his mentions of my involvement. I did help more with this version but Karl is the main one to thank for this round of enhancements. In any case, I highly advise you to try it out. If you have any comments or suggestions, be sure to send them to molefeedback@yahoo.com.

Where are my fields?

December 13, 2007

Recently Karl added the ability to view the non-public fields of objects in our Mole visualizer, a feature he termed BlackOps. However when reviewing it, I noticed that some fields that I know exist were not being displayed. What we were doing – targetType.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.DeclaredOnly) – seemed to be right but it didn’t return the results expected.

So lets take a look at an example.

    public class A

    {

        private string _private;

        internal string _internal;

        protected string _protected;

        internal protected string _internalProtected;

    }

 

    public class B : A

    {

 

    }

If we check the results of GetFields for these two types:

int aFieldCount = typeof(A).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Length;

int bFieldCount = typeof(B).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Length;

When you execute this code, you will find that aFieldCount is 4 but bFieldCount is 3. This is obviously not what we want for Mole since we’re looking to display all the field values (including those not visible to the type itself). The problem is that GetFields will only return Private fields if they are defined by that type – it will not return the private fields of any base classes. The solution is pretty simple – only get the fields defined by each type and walk up the BaseType chain. To get only the fields defined on the type, we add in the BindingFlags.DeclaredOnly flag and then we just use a loop to walk up the base types.

    Type type = typeof(B);

    int fieldCount = 0;

 

    while (null != type)

    {

        fieldCount += type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Length;

        type = type.BaseType;

    }

Mole II

December 13, 2007

Josh Smith and I worked together at the Infragistics WinForms development lab and since I’m now working on WPF, I keep an eye on his blog. I also tend to read through the articles on codeproject. So when I saw that he posted a visualizer for wpf, I was naturally curious. I sent him a couple of thoughts about how he might want to change the visualizer.

If you’re not familiar with visualizers, you can check out this page on Microsoft’s site. Basically a visualizer is a tool used for debugging in Visual Studio. It allows you to provide a “visualization” or representation – hence the name – of an object in the program being debugged. They’re actually very powerful because they allow you to send information back and forth between the debugger and debuggee side.

Anyway, Josh then moved on to work on Mole with Karl Shifflett. I posted a bunch of performance related improvements as well as a number of suggestions (delving/drilling into the properties of objects, viewing the logical tree, etc). In the communications with Josh and Karl that followed, I was asked if I wanted to participate in the development with them.

Karl and Josh worked long hours in developing Mole II. I tried to help out where I could but given my schedule (work and personal) I couldn’t help as much as I would have liked. That aside, Josh and Karl were kind enough to include me as an author on the article. I have to say that both Josh and Karl are talented developers. Since I had worked with Josh before I knew he was intelligent and motivated. I hadn’t had the opportunity to work with Karl before but I must say that he is one of the most enthusiastic and driven developers that I have come across. I think the outcome is a great visualizer for inspecting WPF objects.


Follow

Get every new post delivered to your Inbox.