2013-05-17

Announcement: Async Diagnostics

It is with greatest pleasure that I announce the public (pre)release of Async Diagnostics.

Currently, diagnostics can be a bit... difficult... when dealing with async code. In particular, the call stack is not very useful for diagnostics in asynchronous code.

A Brief Digression on Call Stacks and Causality Stacks

I'll cut to the chase: the call stack is about where you're going next, not where you came from. This means that you should not look to the call stack to find out how your code got into that situation. What you really want is a "causality stack".

This is counter-intuitive to many developers because in the synchronous world, the call stack is the causality stack. But in the asynchronous world, they are very different. Eric Lippert has some great SO answers (1, 2) that clarify what the call stack really is.

There's also a recent MSDN article that explains why call stacks aren't causality stacks. That article includes a fairly involved way to build causality chains that works for Windows Store applications but does not properly handle fork/join scenarios (e.g., Task.WhenAll).

Introducing Async Diagnostics

You can now download a library into your project from NuGet, follow the simple instructions, and you'll get asynchronous diagnostic (causality) stacks for all exceptions thrown in (or through) your assembly.

Example

Consider the following example program. It has reasonably realistic asynchronous method usage; the MainAsync method calls the MyMethodAsync method, which is overloaded to allow cancellation. MyMethodAsync in turn spins up a couple of parallel asynchronous tasks and waits for them both to complete. One of these tasks will throw an exception.

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

class Program
{
    static void Main(string[] args)
    {
        MainAsync(args).Wait();
    }

    static async Task MainAsync(string[] args)
    {
        try
        {
            await MyMethodAsync("I'm an asynchronous exception! Locate me if you can!");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.ReadKey();
        }
    }

    static Task MyMethodAsync(string message)
    {
        return MyMethodAsync(message, CancellationToken.None);
    }

    static async Task MyMethodAsync(string message, CancellationToken token)
    {
        var task1 = Task.Delay(1000);
        var task2 = Task.Run(() => { throw new InvalidOperationException(message); }); // (line 33)
        await Task.WhenAll(task1, task2);
    }
}

If you run this program, you'll see output like this:

System.InvalidOperationException: I'm an asynchronous exception! Locate me if you can!
   at Program.<>c__DisplayClass4.<MyMethodAsync>b__3() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 33
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Program.<MyMethodAsync>d__6.MoveNext() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 34
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Program.<MainAsync>d__0.MoveNext() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 16

If you're familiar with mangled call stacks, you can see from the first entry that the exception was raised from a lambda expression in MyMethodAsync, and you even get the file name and line number. But the real question is: how did the program get in this state? You can often answer that question by answering the closely related questions: what called this method, and what called the calling method, etc? A regular call stack just isn't sufficient to answer those questions for asynchronous code. You need a causality stack.

First, add the Nito.AsyncEx.AsyncDiagnostics package to the solution. Be sure to include Prerelease packages:

Once it's installed, it'll bring up some installation/usage instructions. First, in one of your source files, apply the AsyncDiagnosticAspect to your assembly. Then, locate the place where you display or log your exceptions, and change ToString to ToAsyncDiagnosticString:

using System;
using System.Threading;
using System.Threading.Tasks;
using Nito.AsyncEx.AsyncDiagnostics;

[assembly: AsyncDiagnosticAspect]

class Program
{
    static void Main(string[] args)
    {
        MainAsync(args).Wait();
    }

    static async Task MainAsync(string[] args)
    {
        try
        {
            await MyMethodAsync("I'm an asynchronous exception! Locate me if you can!");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToAsyncDiagnosticString());
            Console.ReadKey();
        }
    }

    static Task MyMethodAsync(string message)
    {
        return MyMethodAsync(message, CancellationToken.None);
    }

    static async Task MyMethodAsync(string message, CancellationToken token)
    {
        var task1 = Task.Delay(1000);
        var task2 = Task.Run(() => { throw new InvalidOperationException(message); });
        await Task.WhenAll(task1, task2);
    }
}

With these few changes, the new output is the same, except for some additional information printed at the end of the exception stack trace:

System.InvalidOperationException: I'm an asynchronous exception! Locate me if you can!
   at Program.<>c__DisplayClass4.<MyMethodAsync>b__3() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 36
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Program.<MyMethodAsync>d__6.<MoveNext>z__OriginalMethod() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 37
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Program.<MainAsync>d__0.<MoveNext>z__OriginalMethod() in e:\work_\projects\ConsoleApplication8\ConsoleApplication8\Program.cs:line 19
Logical stack:
   async Program.MyMethodAsync(String message, CancellationToken token)
   Program.MyMethodAsync(String message)
   async Program.MainAsync(String[] args)
   Program.Main(String[] args)

Now there's a nice "logical stack" stuck on the end of the exception dump. Unlike the exception call stack, the "logical stack" is actually a causality stack, which is much more useful when debugging asynchronous code. As you can see, the logical stack leads us directly to the location of the exception, and (more importantly) shows how we got there.

Side note: the original exception details are included in ToAsyncDiagnosticString because it does contain some information that is not tracked by the async diagnostic stack. For example, you can look at the top frame in the (synchronous) call stack (Program.<>c__DisplayClass4.<MyMethodAsync>b__3()) and infer that in fact the exception is thrown from a lambda expression and not directly from MyMethodAsync. The synchronous call stack also includes other information such as file names and line numbers that is not (currently) included in the logical stack.

Ready to go one step further? You can tie into the diagnostic stack and add whatever additional data you want:

using System;
using System.Threading;
using System.Threading.Tasks;
using Nito.AsyncEx.AsyncDiagnostics;

[assembly: AsyncDiagnosticAspect]

class Program
{
    static void Main(string[] args)
    {
        MainAsync(args).Wait();
    }

    static async Task MainAsync(string[] args)
    {
        try
        {
            await MyMethodAsync("I'm an asynchronous exception! Locate me if you can!");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToAsyncDiagnosticString());
            Console.ReadKey();
        }
    }

    static Task MyMethodAsync(string message)
    {
        using (AsyncDiagnosticStack.Enter("  My message is: " + message))
        {
            return MyMethodAsync(message, CancellationToken.None);
        }
    }

    static async Task MyMethodAsync(string message, CancellationToken token)
    {
        var task1 = Task.Delay(1000);
        var task2 = Task.Run(() => { throw new InvalidOperationException(message); });
        await Task.WhenAll(task1, task2);
    }
}

And whatever string you give it gets included in the logical stack:

Logical stack:
   async Program.MyMethodAsync(String message, CancellationToken token)
     My message is: I'm an asynchronous exception! Locate me if you can!
   Program.MyMethodAsync(String message)
   async Program.MainAsync(String[] args)
   Program.Main(String[] args)

Limitations

Async Diagnostics only works on the full .NET framework. So it's great for WPF or ASP.NET apps, but won't work for Windows Store, Phone, or Silverlight.

Async Diagnostics works best when you build in Debug mode. In Release mode, the compiler may inline method calls, and then they don't show up in the logical stack. However, any data you explicitly add to the diagnostic stack will always be included.

Async Diagnostics requires full trust. There is no support for partial trust.

There is a definite runtime impact. Your code will certainly run slower with async diagnostics active. Currently, there is no way to turn async diagnostics on or off at runtime; it is a compile-time-only option. However, you can reduce the runtime impact by only applying AsyncDiagnosticAspect to certain types or namespaces (either by placing the attribute only on the type(s) that need it or by using PostSharp multicasting).

I do attempt to minimize the runtime impact of Async Diagnostics. I do as much processing as possible at compile time. At runtime, I use immutable collections exclusively to maximize memory sharing. However, the runtime impact is still non-trivial. It is possible to leave Async Diagnostics on in production, but you'll want to do performance testing before making that decision.

AsyncDiagnosticAspect may be applied to assemblies or types. It does not work correctly when multicast onto methods. I expect this will be fixed after PostSharp 3.1 is released.

Async Diagnostics currently requires a paid version of PostSharp (Professional or higher). If you don't have a PostSharp Professional license, you can evaluate it for free for 45 days. I expect PostSharp 3.1 will allow Async Diagnostics to work with the Community (free) version of PostSharp.

How It Works

It's actually quite simple. Async Diagnostics is an implicit async context containing a stack of strings (very similar to the example in this blog post) and uses PostSharp to inject pushes and pops into your methods at compile time.

Error Logging Frameworks

Async Diagnostics works by capturing the diagnostic stack at the time the exception is thrown, and placing it on the Exception.Data dictionary. Many error logging frameworks ignore the Data property, but if you Google around you'll find some solutions for log4net and hacks for ELMAH and nLog. As of this writing, Microsoft's Enterprise Library is the only logging framework I know of that does include Data values by default.

Call to Action

Please download Async Diagnostics and take it for a spin! I've run a number of tests but haven't tried it on really complex code bases. Let me know (in the AsyncEx library discussions) if it doesn't work!

2013-05-16

Announcement: C# MVP

On the "personal achievement" side of things, I'm pleased to announce that I've been given the Microsoft Most Valuable Professional award for C#.

I've read about the MVP award before (both good and bad), and I thought I'd write out my own perspective of what it is and is not. (I'm just talking about the "programmer" MVPs here, e.g., C#, VB, etc., not the "user" MVPs, e.g., Excel).

It's Not: A Certification

A certification is something you earn. I hold a number of Microsoft certifications, which I earned by practicing and studying and then passing exams. Certifications (attempt to) measure a skill set, and achieving a certification indicates that one has those skills.

The MVP award is different. The MVP award is given to people who have had an impact on technical communities through their willingness to help others. It's a much fuzzier definition; there's no specific set of actions that anyone can do that are guaranteed to "earn" them an MVP.

Another difference is that there's no limit to the number of certifications. Every person in the world could decide to get a Windows Store Apps certification, and that would be fine.

In contrast, there is a definite limit to the number of MVPs. As of now, there's only about 3,800 MVPs worldwide. Also, the MVP award is a yearly award, so if an MVP stops contributing to the technical community, then they may not get their MVP status renewed the following year.

It's Not: A Super Programmer Designation

Being an MVP actually has little to do with being a great developer. A lot of other people have criticized the MVP program for letting in less-than-stellar developers (and in some cases, non-developers). But that seems fine to me; the primary filter for being an MVP is not programming prowess; it's how much you help other developers.

It's Not: A Way to Control Microsoft

If you read some of the writings out there by former MVPs, you'll find that a number of them think the program is useless because MVPs don't get to drive the decisions at Microsoft. It is true that MVPs have (slightly) more access to Microsoft personnel than average developers, and (at least in the past) some Microsoft product groups have invited feedback from MVPs, but that doesn't mean that the MVPs control the decisions. At the end of the day, Microsoft will do what they think is best for Microsoft.

Similarly, MVPs have access to a lot of NDA information, but Microsoft does not share everything with its MVPs. MVP leaks are a historical fact, and when Microsoft has a game it's playing close to the chest, of course they don't release the details to MVPs before the hand is played out. In the past this has caused some hurt feelings among MVPs, since they were purposely kept in the dark for strategic reasons.

My take on this is simple: an MVP award does not entitle the holders to any secret information or influence on product development. If you do get this as part of your MVP, bully for you and make good use of it! But if not, well, you're just not entitled to it. Every MVP area (e.g., C# vs F# vs Windows Phone vs Azure) is different and interacts with its MVPs differently; some have access to NDA material, some have input on product design, some get advance warning of game-changers. Others don't.

It Is: A Recognition

The MVP award is primarily a recognition for work you've already done over the previous year. It doesn't really come with any guarantees; it's just recognizing work that's already been done.

Personally, I was honored to receive the MVP award. For the last few years I've thought it would be nice to be an MVP, but I decided I would never nominate myself, nor would I ask (or hint) for anyone else to nominate me. Rather, I'd just be myself and let the chips fall where they may. I still have no idea who nominated me as an MVP, but thank you, whoever you are.

A nice side effect of the MVP award is that I get a lot of really cool toys; a lot of the popular tools provide free MVP licenses, and this really lets me explore a lot of things I've only read about. IntelliTrace, here I come! :)

It's Not: Mensa

I just have to include this point because I literally laughed out loud while unpacking my MVP award.

The photo at the beginning of this post is my actual (physical) MVP award. The circular year part comes off, like so:

I assume this is done so that the big, heavy part of the award is only given once and if you are still an MVP next year they only send you another little circular part.

Just in case any MVPs couldn't figure out how to assemble the award, Microsoft was kind enough to include instructions:

Apparently, the Microsoft MVP program ain't exactly Mensa. ;)

2013-05-15

Announcement: AsyncEx Stable Release

A lot of my posts have to do with asynchronous code one way or another. Along the way, I've compiled a lot of useful helper classes into a library called Nito.AsyncEx.

Today I am pleased to announce that the first public, official release of AsyncEx has gone live. Try it out and see what you think! (And go ahead and yell at me if it's broken).

Release Notes

With this first stable release of AsyncEx, I restructured the DLL and NuGet packages slightly (details on the library homepage). I also had to make some difficult decisions about cutting some of the APIs that were most likely to change in the future.

Redesigned Features

These types have gone through a redesign since the last prerelease:

  • The old AsyncWaitQueue (which was possibly the worst API I've ever written) was completely reworked into a properly-designed IAsyncWaitQueue.
  • TaskCompletionNotifier has also been redesigned and renamed to NotifyTaskCompletion. This was more of a minor correction in the design.
Semantic Changes

The AsyncFactory FromApm methods now propagate exceptions directly from Begin* methods. This matches TaskFactory.FromAsync behavior, so it should be less surprising for new adopters.

Moving Stuff Around
  • Moved synchronous task extensions (e.g., Task.WaitAndUnwrapException) into namespace Nito.AsyncEx.Synchronous because they are normally not needed.
  • Moved dataflow support into a separate Nito.AsyncEx.Dataflow NuGet package. So if you upgrade and all your dataflow support breaks, you'll need to download the new NuGet package.
Removed and Probably Not Coming Back

The awaitable interfaces (IAwaitable, IAwaiter, and friends) have been removed. They are only helpful (but not required) in some advanced custom awaitable situations and they don't properly support ICriticalNotifyCompletion.

TaskFactory.With has also been removed. While this API makes sense, it just isn't that helpful.

Removed but Will Probably Come Back after They Bake a Bit More
  • Custom types derived from Task (TaskBase, TaskBaseWithCompletion). These are useful conceptually but need some more API work and testing.
  • ETW tracing. All ETW tracing has been disabled for this release; I'm working on making the ETW tracing more consistent across all types. ETW tracing will definitely be supported in a future release.
New features
  • Added several more CancellationTokenHelpers: None, Canceled, and Timeout.
  • Finished Task.Then implementations.

2013-05-14

Announcement: Speaking at ThatConference

I have been chosen to speak at ThatConference!

I'm a little nervous since I have not attended ThatConference before, but I have been to CodeMash twice so that counts for something, right?

My session is Scaling Your Servers with Async/Await. I'll be covering all kinds of helpful information on developing with async/await on the server side. Most async/await talks focus on the client side - and don't me wrong, async/await is certainly needed for client apps! - but server-side async is often overlooked or put on the back burner. I'll be addressing server-side async from concepts to best practices to diagnostics.

I'm really excited for my talk, and I hope to see you there!

2013-05-13

Announcement: Over 200 Posts!

This is the first post of an "announcement week". It just so happens that I have a few announcements to make, so this week instead of my regular posts I'll be posting only announcements.

The first announcement is this: I've reached over 200 posts on my blog! (This post is actually number 208). I hardly ever look at my blog stats, but I thought today I'll make an exception since this is sort of a blog post that's about this blog...

All together, my blog has had more than 400,000 pageviews since I published my first post in June of '08.

The vast majority of my readers come from Google or Stack Overflow, which means that they won't actually see this message. Thanks to those of you who are reading this! :)

The all-time "most famous" posts are currently:

  1. The (quite old) Reporting Progress from Tasks.
  2. My Async and Await Intro (of course).
  3. Detection of Half-Open (Dropped) Connections, part of my TCP/IP .NET Sockets FAQ.

However, if you look at recent trends, Reporting Progress from Tasks is heading down in the rankings while Async and Await is coming up fast. So I'd expect the all-time rankings to change soon.

I'd like to close with a big "thank you" to all my readers out there! If you're reading this, you're probably a "regular", so special thanks to you for putting up with my crazy talk on a regular basis! :)

2013-05-09

Task.Run vs BackgroundWorker, Round 1: The Basic Pattern

~ Ready? ~

I'm going to just use a simple Windows Forms framework for my test code. WinForms is a pretty common denominator for most developers; just keep in mind that both BackgroundWorker and Task.Run are using SynchronizationContext underneath, so these same principles apply regardless of platform (WPF, Windows Store, MonoTouch, MonoDroid, Windows Phone, Silverlight, ASP.NET, etc). I'm just using WinForms because it's simple and pretty much everyone knows it.

The Basic Pattern: Do Work

The core problem that BackgroundWorker originally solved was the need to execute synchronous code on a background thread. If you're using BackgroundWorker for asynchronous or parallel work then just stop; you're not using the right tool in the first place. The core problem for BackgroundWorker is to execute synchronous code on a background thread.

Our example (synchronous) action is just going to sleep for a second.

The Basic Pattern: Completion

In almost every real-world scenario, we also want to be notified when the background operation has completed. Also, most of the time, we want our "handle the completion" code to run on the original context (e.g., a UI context so we could update the UI). It would be best if this marshaling back to the UI thread could be automatic.

Our example completion code will just toss up a message box.

~ Fight! ~

BackgroundWorker

private void button1_Click(object sender, EventArgs e)
{
    var bgw = new BackgroundWorker();
    bgw.DoWork += (_, __) =>
    {
        Thread.Sleep(1000);
    };
    bgw.RunWorkerCompleted += (_, __) =>
    {
        MessageBox.Show("Hi from the UI thread!");
    };
    bgw.RunWorkerAsync();
}

Task.Run

private async void button2_Click(object sender, EventArgs e)
{
    await Task.Run(() =>
    {
        Thread.Sleep(1000);
    });
    MessageBox.Show("Hi from the UI thread!");
}

Discussion

Both of these are pretty straightforward. Both of them will marshal our MessageBox.Show back to the UI thread, so we don't have to worry about it.

The BackgroundWorker code does suffer from more "ceremony", since it has to deal with events. It's also a bit awkward in that you have to wire up your events first and then explicitly start the work going. The equivalent Task.Run is simpler - not a lot simpler, but simpler nonetheless.

2013-05-02

Task.Run vs BackgroundWorker: Intro

This is an introductory post for a new series that I'll be doing comparing BackgroundWorker to Task.Run (in an async style). I always recommend Task.Run, and I have already written a long post describing why, but I still see some developers resisting the New Way of Doing Things (TM). So this will be a short series where I'll compare the code side-by-side in different scenarios and show why I think Task.Run is superior in every way.

To be clear, this series will show supported scenarios that both BackgroundWorker and async Task.Run were designed for. I won't be picking on any scenarios that BackgroundWorker doesn't support. Except today. :)

Scenarios Not Supported by BackgroundWorker

One of the design problems of BackgroundWorker is that the semantics get surprising when nesting; if you create (and start) a BackgroundWorker from within another BackgroundWorker, the events on the inner BackgroundWorker are raised on the thread pool. I explain why this happens in my SynchronizationContext article, complete with pretty pictures (don't laugh! I worked hard on those!).

A similar problem is that BackgroundWorker doesn't work well with async code. An async DoWork handler will exit early, causing the RunWorkerCompleted to fire before the method is completed.

Also, it's difficult to call async code from within a (properly synchronous) DoWork; you either have to call Task.Wait or establish your own async-friendly synchronization context (e.g., AsyncContext).

On the other hand, Task.Run does support these scenarios: nesting, async delegates, and calling async code are all perfectly natural.

This is really just because the design of BackgroundWorker is dated. It was fine for its time, but it was obviously skipped over when Microsoft was updating the BCL with async support. That should tell us something.

As we go through this series, I hope to convince other developers that BackgroundWorker really is dead at this point and should not be used for new development. In every situation, a solution based on Task.Run will produce cleaner code.