2014-04-17

Announcement: Book

I am very pleased to announce that I have finished writing a book!

The title is quite a mouthful: Concurrency in C# Cookbook: Asynchronous, Parallel, and Multithreaded Programming. The goal of this book is to introduce developers to asynchronous, parallel, and reactive code in a way that is helpful and down-to-earth.

I have to say that writing this book took a lot more time than I originally thought! I should be able to resume a more normal pace of blogging shortly. :)

2014-04-08

Announcement: MSDN "async MVVM" articles

Oops, not sure how I missed making this announcement! Sorry for the late notice!

I have two articles published recently in MSDN magazine, both dealing with patterns for async MVVM applications. The first one is on asynchronous MVVM data-binding, and the second one is on asynchronous MVVM commands.

2014-04-07

Announcement: AspNetBackgroundTasks NuGet library

Yielding to popular demand - and against my better judgement - I have created a NuGet package for the code I previously wrote for handling "fire-and-forget" tasks in ASP.NET.

Why is this against my better judgement? Because it's almost always the wrong solution, and making the wrong solution easy is digging a pit of failure rather than a pit of success. However, a lot of people want to use it anyway (and many people are actually using worse solutions because I didn't make this one easy), so I put in plenty of warnings and published it on GitHub and on NuGet.

2014-04-04

Announcement: GRDevDay 2014 slides available

This year at GRDevDay 2014 I was honored to present two sessions.

The slides and demo code are now available! Please note that there are some hidden slides with additional information that I had to remove for time considerations, so even if you came to the talks, there's some helpful stuff in the slides.

Introduction to async on ASP.NET was a pretty well-attended talk (~30 people). It covered how asynchronous requests work in ASP.NET, how async/await work in C#, and how async/await work specifically with ASP.NET.

Asynchronous? Parallel? Reactive? HELP! was a very well-attended talk (~45 people, standing-room only). It was a gentle introduction to various forms of concurrency: parallel processing (using the Parallel class and PLINQ), asynchronous code (using async/await), reactive coding (using Rx), and an overview of TPL Dataflow. If you ever wondered when to use which, take a look at this one.

I did record both talks, but have not had the time to do post-production. I'll update here and on Twitter when (if) I get around to it. :)

2014-03-13

A Cross-Domain Singleton

In my current position, I've had to learn a lot more details about two big aspects of the .NET runtime: AppDomains and COM interop. Until about a year ago, I had learned exactly enough of those technologies to pass the Microsoft certification exams, and that was it! I had never used them in production and never intended doing so. At my current job, however, I have no choice, so I've been learning quite a bit about AppDomains and COM interop over the last few months.

On a side note: blech. I wish I could have remained ignorant. :)

Anyway, the way our product uses AppDomains, it would benefit from a "cross-AppDomain singleton" for certain lookup operations (including cache). I spent some time playing with this idea over Christmas break, and Googled up several implementations. None of them were quite complete, though; many punted on thread safety, which was an absolute necessity for my scenario.

So, I wrote my own. Initially I borrowed heavily from other AppDomain-aware singletons, until I had a minor epiphany. Since this was a true application-level singleton, it would never be destroyed, and the correct place to initialize it is in the default AppDomain. The "default AppDomain" is the first one in a process, and it can never be unloaded. All non-default AppDomains then request the instance from the default AppDomain. Those other AppDomains can come and go, but the default AppDomain (including all cross-AppDomain singletons) would remain.

Once I decided to assign all singletons to the default AppDomain, the implementation simplified significantly. The algorithm is different based on whether an instance is requested from the default or a non-default AppDomain.

When an instance is requested on a non-default AppDomain, it will first check to see if there is a local, cached copy in the current AppDomain. If there is, then it is returned immediately. Otherwise, it will attempt to get the instance from an AppDomain value stored on the default AppDomain. If that value is not found, then it invokes a method on the default AppDomain that just requests the instance.

When an instance is requested on the default AppDomain, it will first check to see if the instance has been created, and return it immediately if so. Otherwise, it will create a new instance and set that instance as an AppDomain value on the default AppDomain, and then return the instance.

This implementation is fully threadsafe, using Lazy<T> for all lazy construction. The only drawback to this solution is that it does use a tiny bit of COM interop to a deprecated interface (ICorRuntimeHost); if anyone knows of a better way to get the default AppDomain, I'm all ears!

Also, I cheated just a little bit to simplify lifetime management. By default, remote proxies will time out if you don't use them for 10 minutes, and this is no good since my singleton type caches the proxies locally for each AppDomain. So, my singleton actually creates a wrapper around the instance, and caches proxies to that wrapper (and the wrapper proxies never expire). However, this means that each time the code accesses the singleton instance, a new proxy is actually created and returned - so it's ideal for the occasional-access scenario but not so much for the constant-access scenario. If the proxy creation slows you down too much, then you can use the CachedInstance property instead, which will cache the actual (unwrapped) instance; and in that case the responsibility falls back on you to properly handle proxy lifetimes.

The full public API is quite simple:

namespace DomainAwareSingleton
{
    // A domain-aware singleton. Only one instance of T will exist, belonging to the default AppDomain. All members of this type are threadsafe.
    public static class Singleton<T> where T : MarshalByRefObject, new()
    {
        // Gets the process-wide instance.
        // If the current domain is not the default AppDomain, this property returns a new proxy to the actual instance.
        public static T Instance { get; }

        // Gets the process-wide instance.
        // If the current domain is not the default AppDomain, this property returns a cached proxy to the actual instance.
        // It is your responsibility to ensure that the cached proxy does not time out; if you don't know what this means, use Instance instead.
        public static T CachedInstance { get; }
    }
}

And the code is on GitHub.

2014-02-20

Synchronous and Asynchronous Delegate Types

Delegate types can be confusing to developers who are learning more about async and await.

There is a pattern to asynchronous delegate types, but first you must understand how asynchronous methods are related to their synchronous counterparts. When transforming a synchronous method to async, one of the steps is to change the return type. If MyMethod returns void, then MyMethodAsync should return Task. Otherwise (that is, if MyMethod returns T), then MyMethodAsync should return Task<T>. This modification of the return type is what makes delegate type translation a bit tricky.

This return-type transformation can also be applied to delegate types. If the delegate is one of the Action delegate types, then change it to Func and append a Task (as the return type). Otherwise (that is, the delegate is already a Func), change the last type argument from T to Func<T>.

This a bit complex to describe in words, so here's a little table that lays out several examples. Each synchronous example is paired with its asynchronous counterpart:

Standard TypeExample LambdaParametersReturn Value
Action
Func<Task>
() => { }
async () => { await Task.Yield(); }
NoneNone
Func<TResult>
Func<Task<TResult>>
() => { return 13; }
async () => { await Task.Yield(); return 13; }
NoneTResult
Action<TArg1>
Func<TArg1, Task>
x => { }
async x => { await Task.Yield(); }
TArg1None
Func<TArg1, TResult>
Func<TArg1, Task<TResult>>
x => { return 13; }
async x => { await Task.Yield(); return 13; }
TArg1TResult
Action<TArg1, TArg2>
Func<TArg1, TArg2, Task>
(x, y) => { }
async (x, y) => { await Task.Yield(); }
TArg1, TArg2None
Func<TArg1, TArg2, TResult>
Func<TArg1, TArg2, Task<TResult>>
(x, y) => { return 13; }
async (x, y) => { await Task.Yield(); return 13; }
TArg1, TArg2TResult

The table above ignores async void methods, which you should be avoiding anyway. Async void methods are tricky because you can assign a lambda like async () => { await Task.Yield(); } to a variable of type Action, even though the natural type of that lambda is Func<Task>. Stephen Toub has written more about the pitfalls of async void lambdas.

As a closing note, the C# compiler has been updated in VS2012 to correctly perform overload resolution in the presence of async lambdas. So, this kind of method declaration works fine:

Task QueueAsync(Action action); // Sync, no return value
Task<T> QueueAsync<T>(Func<T> action); // Sync with return value
Task QueueAsync(Func<Task> action); // Async, no return value
Task<T> QueueAsync<T>(Func<Task<T>> action); // Async with return value