Debugging Fun with the Async CTP

I was writing a short talk about the Async CTP and as part of that, I wrote this little WPF form which goes off to my local web server to grab an image and display it;

image produces image

when you click on the “Get Image” button that that image is just served up by my local web server and accessed with an HTTP GET.

The code for that looks something like this where OnGetImage is the event handler for the button on the screen;

namespace TaskPlayground
{
  using System.IO;
  using System.Net;
  using System.Windows;
  using System.Windows.Media.Imaging;

  public partial class MainWindow : Window
  {
    static readonly string url = "http://localhost/photo1.jpg";

    public MainWindow()
    {
      InitializeComponent();
    }
    void OnGetImage(object sender, RoutedEventArgs e)
    {
      OnGetImageInternal();
    }
    async void OnGetImageInternal()
    {
      WebClient client = new WebClient();
      byte[] bits = await client.DownloadDataTaskAsync(url);
      FillInPicture(new MemoryStream(bits));
    }
    void FillInPicture(MemoryStream stream)
    {
      stream.Seek(0, SeekOrigin.Begin);
      BitmapImage bitmapImage = new BitmapImage();
      bitmapImage.BeginInit();
      bitmapImage.StreamSource = stream;
      bitmapImage.EndInit();
      this.image1.Source = bitmapImage;
    }
  }
}

but what I thought really highlighted the workings of things was the debugging experience in that if I go add some “breakpoints”;

    void OnGetImage(object sender, RoutedEventArgs e)
    {
      OnGetImageInternal();
      // Breakpoint 1.
      Debugger.Break();
    }
    async void OnGetImageInternal()
    {
      WebClient client = new WebClient();
      byte[] bits = await client.DownloadDataTaskAsync(url);

      // Breakpoint 2.
      Debugger.Break();
      FillInPicture(new MemoryStream(bits));
    }

Then I think most (all?) .NET developers prior to the Async CTP would have been quite happy to borrow money in order to bet that breakpoint 2 would fire before breakpoint 1 and then they’d have retired to a desert island somewhere Smile 

This is the natural order of things. It’s what we intuitively “know”.

Of course, with the Async CTP “everything you know is wrong” because breakpoint 1 fires before breakpoint 2 and, even more surprisingly if you’ve not been following this stuff too closely is that my debugger’s threading window shows me that breakpoint 1 runs on my main thread;

image

and that breakpoint 2 also runs on my main thread;

image

That is ( as I talked about in previous posts and is covered very well elsewhere ) the async CTP work is SynchronizationContext aware and I think that you can see that from the callstacks here although I’m not 100% certain that I’m looking at the right frames as they get a bit “deep” in their interactions with the WPF Dispatcher in this case;

image

"We’re not in Kansas any more” has become my stock phrase of late – this is not your father’s C# ( or VB for that matter ) Winking smile

If you want to get this from “the horse’s mouth” then, of course, you should go watch the talk that Anders gave at BUILD ( make sure that you watch the Smooth Streaming format version at full screen rather than the default version which doesn’t smooth stream and gives you a slightly more shabby experience );

Visual Studio Async CTP–Simple Examples in ‘Quiz’ Form

This one’s just a bit of “fun” for a Friday afternoon ( depending on how you define “fun” Winking smile ).

I was writing some asynchronous code yesterday in JavaScript and I then had cause to duplicate it in .NET using the await support of the Async CTP which I’ve tried to write about before ( generally and combined with Rx ).

This led into a debate with a colleague where we started passing bits of code backwards and forwards and got down to some simple cases and I thought I’d share here in the form of a “quiz” Confused smile

This isn’t meant to be even slightly comprehensive, it’s just that I found that we tended to start with small, simple examples and then build them up a little and so I thought I’d re-use some of those pieces of code here.

So…roll up and see how many points you can score with a few quiz questions on the async CTP.

Before we get going…

Before we start – I’m using TaskEx.Delay here and you might have the async CTP but you might not have seen TaskEx.Delay so I’ll say from the docs that it;

Starts a Task that will complete after the specified due time.”

the bolding is mine because I think it’s vital to know that it starts a task rather than just creates one.

Note that there are no “trick” questions with the exception of question 2 which is just nasty.

and we’re not quite ready yet…

We create some tasks here which will need assigning to threads in order to run them – that introduces an element of non-determinism (e.g. the threadpool can pretty much do whatever it likes) so where I’m saying “how long does this piece of code take to run” I’m really saying “how long does it take to run given that the scheduler does more or less what you’d expect it to”).

This introduces an element of non-determinism into the quiz Winking smile

Now…on with the quiz;

Question 1 ( 5 points )

(Approximately) how many seconds will this program print to the console?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    TaskEx.Delay(TimeSpan.FromSeconds(3));

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);

  }
}

Question 2 ( 20 points )

Again, approximately how many seconds will this program print to the console?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static async void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    await TaskEx.Delay(TimeSpan.FromSeconds(3));

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
}

Question 3 ( 5 points )

Ok, I apologise for the last question, that was really nasty. Let’s get back onto more reasonable ground here with a better class of question. What about this one?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    TaskEx.Delay(TimeSpan.FromSeconds(3)).Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
}

Question 4 ( 5 points )

And, to rebuild more trust in the pillock setting the questions Winking smile here’s a similar situation,  what will this one print?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    await TaskEx.Delay(TimeSpan.FromSeconds(3));
  }
}

Question 5 ( 10 points )

Just to check that you’re still with me, looking at the code example below and the assertions within it, which of the assertions will fail and throw a big, nasty dialog to the screen?

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

class Program
{
  static int threadId;

  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    threadId = Thread.CurrentThread.ManagedThreadId;

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    Debug.Assert(Thread.CurrentThread.ManagedThreadId == threadId);

    await TaskEx.Delay(TimeSpan.FromSeconds(3));

    Debug.Assert(Thread.CurrentThread.ManagedThreadId == threadId);
  }
}

Possible Answers ( these would be a,b,c if I could get Live Writer to do it Smile )

  1. The one on line 24.
  2. The one one line 28.
  3. Both of the ones on line 24 and on line 28.
  4. None of them.
  5. I’m still not talking to you after question number 2. That was a really nasty thing to put so early in the quiz.

Question 6 ( 5 points )

Back from the leisures of multiple choice answers to working out timings – how long will this one print to the console?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    await TaskEx.Delay(TimeSpan.FromSeconds(3));
    await TaskEx.Delay(TimeSpan.FromSeconds(2));
  }
}

Question 7 ( 10 points )

And we’re still stuck in the world of timings, what about this one?

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    for (int i = 0; i < 3; i++)
    {
      await TaskEx.Delay(TimeSpan.FromSeconds(3));
      await TaskEx.Delay(TimeSpan.FromSeconds(2));
    }
  }
}

Question 8 ( 10 points )

Starting to act a little differently;

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    await TaskEx.WhenAll(
      TaskEx.Delay(TimeSpan.FromSeconds(3)),
      TaskEx.Delay(TimeSpan.FromSeconds(2)));
  }
}

Question 9 ( 5 points )

Very similar;

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    await TaskEx.WhenAny(
      TaskEx.Delay(TimeSpan.FromSeconds(3)),
      TaskEx.Delay(TimeSpan.FromSeconds(2)));
  }
}

Question 10 ( 10 points )

Back to loops;

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    for (int i = 0; i < 3; i++)
    {
      await TaskEx.WhenAny(
        TaskEx.Delay(TimeSpan.FromSeconds(3)),
        TaskEx.Delay(TimeSpan.FromSeconds(2)));
    }
  }
}

Question 11 ( 15 points )

We’re still with loops but we’re being a little bit more sneaky

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Generic;

class Program
{
  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    sw.Start();

    Foo().Wait();

    sw.Stop();
    Console.WriteLine("The program took {0} seconds", sw.Elapsed.Seconds);
  }
  static async Task Foo()
  {
    List<Task> tasks = new List<Task>();

    for (int i = 0; i < 3; i++)
    {
      tasks.Add(TaskEx.Delay(TimeSpan.FromSeconds(3)));
      tasks.Add(TaskEx.Delay(TimeSpan.FromSeconds(2)));
    }
    await TaskEx.WhenAll(tasks);
  }
}

 

and 11 is where I ran out of steam without wandering away from TaskEx.Delay and into other territory.

Answers ( I think )

I think these are the answers (with a little bit of explanation);

  1. Answer is 0 seconds. There’s no code that waits for anything so it’s just going to start that task and then stop the stopwatch straight away. 5 points.
  2. Answer is “this example doesn’t print anything”. Try it. This is to do with trying to be async inside of main and there’s a thread up at the forums that talks about it. Sorry. Trick question. Nasty. 20 points and if you knew this already then you’ve been there before.
  3. Answer is 3 seconds. We create a Task that delays for 3 seconds and we wait for it. 5 points.
  4. Answer is 3 seconds. This is really the same as question 3 with some more thrown in. 5 points.
  5. Answer is option 2 – the assertion on line 28. When the await completes, some thread has to call the “callback” to continue the work here and it can’t be our main thread because it’s blocked in a call to Wait() so it has to be another thread. Note – in other scenarios where there’s a synchronization context in play, this might be different. 5 points.
  6. Answer is 5 seconds – we first wait for 3 seconds and then for 2 seconds so that’s 5. 5 points.
  7. Answer is 15 seconds – we loop around 3 times waiting for 3 and then 2 seconds so that’s 15. 10 points.
  8. Answer is 3 seconds. We have 2 waits to wait for and the longest is 3. 5 points.
  9. Answer is 2 seconds. We wait for the first wait and the shorted is 2. 5 points.
  10. Answer is 6 seconds. We loop 3 times over the previous scenario doing an await each time so that means 6 seconds. 10 points.
  11. Answer is 3 seconds. We make 6 separate tasks with the longest taking 3 seconds and they all (probably!!!!) run concurrently and then we wait for all of them. 15 points.

Scores

I think there are 90 points up for grabs there so if you managed to genuinely get 50+ I think you’re doing pretty well and have perhaps seen some of this stuff before or played with it.

If you managed 90 then you can feel very proud of yourself.

If you got 0 then you’ve perhaps got some reading to do or perhaps were searching the web for “a sink CTP” and were looking for “Copper Sinks – CTP Systems” – in that case, I can only apologise Winking smile

UK TechDays Virtual Client Conference–Resources

At the UK TechDays online conference last week there were a number of sessions around Silverlight and Windows that I wanted to provide follow-up resources on here.

Session: Modern Windows Applications

  1. Visit Develop For Windows
  2. Download the WPF Ribbon Control and get the information on it here
  3. Download the Windows API Code Pack
  4. Read more about the Code Pack
  5. Learn about the Task Bar with WPF 4 ( and part 2 )
  6. More on the Windows 7 TaskBar
  7. More on Windows 7 Libraries
  8. Windows 7 Sensors
  9. Restart/Recovery for Applications
  10. WindowChrome – altering the non-client area of the window.
  11. Subscribe to the Windows Team blog.

Session: User Interfaces with Touch

  1. Some recent local resources on touch;
    1. Touched ( Part 1 )–Getting Touch for Free
    2. Touched ( Part 2 )–Raw Touch Events
    3. Touched ( Part 3 )–Manipulation and Gesture Support
    4. Touched ( Part 4 )-Simple Example
    5. Touched ( Part 5 )–Touch-Ready Controls
  2. Read more about WPF 4 Multi-touch and more
  3. Check out the Native Extensions for Silverlight Preview 2

Session: Silverlight Platform Overview

  1. Visit Silverlight.Net
    1. Watch videos
    2. Try the QuickStarts
    3. Checkout hands-on labs
    4. Read books
    5. Read whitepapers
  2. Watch the Silverlight Firestarter
  3. Visit Channel 9
    1. Follow Silverlight TV
    2. Subscribe to the Silverlight tag
  4. Follow Silverlight Q&A on StackOverflow.
  5. Subscribe to the Silverlight Team blog.

Session: Buffers Guide to Expression Blend

  1. Visit Expression on the web.
  2. Learn Blend via tutorials, starter kits, etc.
  3. Check out the Toolbox resources
  4. Local resources on Blend;
    1. 20 recent posts on Blend
  5. Subscribe to the Expression Blend team blog.

Session: Silverlight for Line of Business Applications

  1. Refer back to the general section on Silverlight here.

Session: Silverlight and Multi-tier Applications

  1. Silverlight Networking Videos on Channel 9
  2. Visit the RIA Services Site
  3. Visit the OData site.
  4. WCF Data Services on MSDN.
  5. Understand the WCF subset in Silverlight.
  6. Understand the security options in Silverlight for service access.
  7. and again
  8. and again
  9. and again
  10. Understand the Client/Browser HTTP stacks in Silverlight

Session: WCF RIA Services

  1. Visit the RIA Services Site
  2. RIA Services on MSDN
  3. Watch Deepesh at TechEd 2010
  4. Subscribe to Deepesh’s blog.

Session: MVVM and RIA Services

  1. Watch John’s session from PDC 2010.
  2. Read Josh’s article on MVVM.
  3. Subscribe to John’s blog.
  4. Follow the RIA Services resources from the previous session.

Session: Silverlight Apps with PRISM

  1. PRISM on CodePlex
  2. PRISM on MSDN
  3. PRISM videos on Channel 9 ( previous PRISM version )
  4. Subscribe to Karl’s Blog

Session: Premium Media Experiences with Silverlight

  1. Learn about the Silverlight Media Framework.
    1. Watch videos on Silverlight.net
  2. Learn about IIS Media Services
  3. Subscribe to David’s blog.