Welcome to MSDN Blogs Sign in | Join | Help

Beware of local scoping in .NET

Last week Jordan Parker and I were looking at a chunk of code that was evidently leaking memory.  What we discovered wasn't obvious at first so I thought I'd share it with the world.  The code looked something like this:

    void BackgroundThreadProc()
    {
        while (true)
        {
            _waitEvent.WaitOne();

            while (!WorkQueueEmpty())
            {
                WorkItem item = DequeueWorkItem();
                ProcessWorkItem(item);
            }
        }
    }

The idea is that we have a thread that waits to get signaled then flushes a queue of work items and goes back to waiting.  What could go wrong?  Imagine the following sequence of events:

  1. a work item is queued and the background thread is signaled.
  2. the background thread processes the work item and goes back to waiting for a signal.
  3. a long time elapses before another work item is queued.

The problem we ran into is that after 2. the local variable "item" was still in scope.  From the C# perspective, you may think that "item" is out of scope while we're blocked in "WaitOne", however this is merely a language notion.  Local variables in .NET are scoped to methods, which means "item" is a GC root whenever we're executing this method.  This caused the most recently processes WorkItem not to be garbage collected, and that caused anything the WorkItem referenced not to be collected and so on.

We can see this by looking at the IL:

.method private hidebysig instance void BackgroundThreadProc() cil managed

{

.maxstack 2

.locals init (

[0] class WorkerThingy/WorkItem item)

L_0000: ldarg.0

L_0001: ldfld class [mscorlib]System.Threading.AutoResetEvent WorkerThingy::_waitEvent

L_0006: callvirt instance bool [mscorlib]System.Threading.WaitHandle::WaitOne()

L_000b: pop

L_000c: br.s L_001c

L_000e: ldarg.0

L_000f: call instance class WorkerThingy/WorkItem WorkerThingy::DequeueWorkItem()

L_0014: stloc.0

L_0015: ldarg.0

L_0016: ldloc.0

L_0017: call instance void WorkerThingy::ProcessWorkItem(class WorkerThingy/WorkItem)

L_001c: ldarg.0

L_001d: call instance bool WorkerThingy::WorkQueueEmpty()

L_0022: brfalse.s L_000e

L_0024: br.s L_0000

}

Notice that IL declares the locals near the top of the method body.  As far as the CLR is concerned 'item' IS in scope while we're waiting to get signaled.  This is something to keep in mind if you find yourself writing a method that never exits.

Posted by brandf | 1 Comments
Filed under: , , ,

Fun With Animation Part 1 - CompositionTarget.Rendering

image

Rich runtime support for animation is a key component of WPF and a lot can be said about it.  That is why I've started this multi part series of posts on the topic of having fun with WPF animations. 

Typically application animations are used as subtle visual cues (think blinking caret) or not-so-subtle transitions (think Flip3D).  Anyone how has played with the iPhone knows that a little animation can go a long way to making the difference between a boring app and something new and exciting.

In this series you'll learn how use animations in WPF to meet your applications needs, and hopefully I'll get you thinking about how to use animations to enhance the users experience.  Each post in this series will focus on a small part of WPF animation story, starting with today's topic: CompositionTarget.Rendering.

I decided to start with the Rendering event because I think it's the most familiar way to do animation for people coming from a Flash background, and because it's an easy way to dig into the basic concepts of animation before we dig into Timelines, Clocks, Storyboards, and the rest of WPF's animation classes.

Hooking the CompositionTarget.Rendering event will get you inside WPF's rendering loop.  This event is fired once each time WPF decides to render a frame.  Furthermore, and this is important for people trying to save battery life, hooking this event _causes_ WPF to continue rendering frames.  This is why it's important to only hook this event while you're animating, and remove your event handler when you're done.

Inside the event handler you have complete freedom to do whatever you want to any object.  In other words, hooking CompositionTarget.Rendering is very much a "do it yourself" animation system.  Later we'll learn about the "let WPF do it for me" style animation system, but for now we'll learn to manually animate things because it's good to know what's going on under the covers.  Besides, there are times when the Rendering event is the best choice, such as when you want to animate something based interdependencies between multiple objects (as you'll see below) or if you just want to control an animation in a procedural way such as a bouncing ball.

The term "Animation" simply means that something is changing over time.  It's most commonly associated with changing motion over time (movement), but in WPF you can animate almost anything.  In this posts sample we'll create a simple procedural motion animation which tells an element to follow or avoid another element.  This creates interesting motion patterns based on who's following/avoiding who.

The first step is to hook the Rendering event:

            CompositionTarget.Rendering += DancingChildren;

Next we need to create the elements to animate and define which elements to follow/avoid.  I'll use XAML to define the elements (in this case various Shapes) and I'll use the Tag property to define who to follow and who to avoid.  An attached property would also work for this purpose, but we'll keep it simple for now.

<Window x:Class="RenderingEventDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300"
    >
  <Canvas>
    <!-- the format of Tag should be "element_to_follow;element_to_avoid" -->
    <Rectangle Fill="Red" Stroke="Black" StrokeThickness="3" Width="20" Height="20" 
               Name="Square" Canvas.Left="200" Canvas.Top="80" Tag="Rectangle;Squircle"/>
    <Rectangle Fill="Pink" Stroke="Black" StrokeThickness="3" Width="40" Height="20" 
               Name="Rectangle" Canvas.Left="80" Canvas.Top="300" Tag="Circle;Square"/>
    <Ellipse   Fill="Green" Stroke="Black" StrokeThickness="3" Width="20" Height="20" 
               Name="Circle" Canvas.Left="0" Canvas.Top="0" Tag="Ellipse;Rectangle"/>
    <Ellipse   Fill="LightGreen" Stroke="Black" StrokeThickness="3" Width="40" Height="20" 
               Name="Ellipse" Canvas.Left="0" Canvas.Top="200" Tag="Squircle;Circle"/>
    <Rectangle Fill="Blue" Stroke="Black" StrokeThickness="3" Width="20" Height="20" RadiusX="7" RadiusY="7" 
               Name="Squircle" Canvas.Left="30" Canvas.Top="80" Tag="Square;Ellipse"/>
  </Canvas>
</Window>

Next we'll need to change the location of the elements in our Rendering event handler.  This can be done in a number of ways, but I've chose to use the Canvas.Top & Canvas.Left attached properties.

        private void DancingChildren(object sender, EventArgs e)
        {
            Canvas root = this.Content as Canvas;
            Point center = new Point(this.ActualWidth / 2.0, this.ActualHeight / 2.0);
            foreach (FrameworkElement child in root.Children)
            {
                string[] tag = ((string)child.Tag).Split(';');
                Point follow = GetLocation((FrameworkElement)FindName(tag[0]));
                Point avoid = GetLocation((FrameworkElement)FindName(tag[1]));
                Point me = GetLocation(child);

                // impulse's tweaked to come close to an orbit around the center
                Vector attract = (follow - me) * 0.1;
                Vector repel = (me - avoid) * 0.1555;
                Vector toCenter = (center - me) * 0.099;

                SetLocation(child, me + attract + repel + toCenter);
            }
        }

        private void SetLocation(FrameworkElement child, Point point)
        {
            Canvas.SetLeft(child, point.X);
            Canvas.SetTop(child, point.Y);
        }

        private Point GetLocation(FrameworkElement frameworkElement)
        {
            return new Point(Canvas.GetLeft(frameworkElement), Canvas.GetTop(frameworkElement));
        }

As you can see we're incrementally moving all elements in the direction of the center & in the direction of the follow element & in the direction away from the avoid element.  The relative strength of each term is tweaked to put the elements into an orbit, but you can modify it to converge/diverge.  Changing the follow/avoid Tags also changes the movement behavior in interesting ways.

To see it in action you can run the attached project.

The astute reader may notice a major shortcoming with the sample I've shown.  Is the motion frame-rate independent?  No.  In the example I've shown the motion is dependent on how fast WPF decides to render.  On Vista this is typically clamped to the monitors refresh rate, so on my system it's 75Hz.  On a system with a refresh rate of 60Hz this animation would be slower.  It's usually a good idea to avoid being frame-rate dependent while animating, so I'll talk about strategies for doing this in the next post in this series.

The birth of a new blog.

Hello world.

Yes, another blog has just been born.  I feel obligated to say a bit about what this blog is going to be about, so here it goes.

I'm a developer at Microsoft on the WPF team, so much of the content here will relate to WPF.  On the other hand, I have broad interests so I want this blog to be a place where I can talk about software trends, languages, debugging, graphics, patterns, and just about anything else I find interesting in the tech world.

In future posts, I'll talk a little bit more about myself and what exactly I do on the WPF team.  I want to keep this post short so you'll have to stay tuned for that.

Posted by brandf | 1 Comments
Filed under: ,
 
Page view tracker