static void

Async

The .net libraries have higher-level APIs for async work (so you don't have to manage the low level Threading).

Asynchronous patterns in FCL

There are 3 main patterns in .net:

NB: concurrency (parallelism) isn't quite the same as asynchronous, but the Task combination methods .WhenAll and .WhenAny enable concurrency.

Task

Task is a higher level API for managing threads, and is enhanced in .net 4.5 with awaiters.

Task corresponds to what other APIs call a "Future" or "Promise".

ThreadsTasks
new Thread(Method).Start(); //.net 4.0
Task.Factory.StartNew(Method);
//.net 4.5
Task.Run(Method);

Tasks are always Started.
Thread.Sleep(1000); Task.Delay(1000); //.net 4.5
thread.Join(); task.Wait();
Task is Disposable, but generally shouldn't be disposed (it can hold WaitHandle resources, but rarely). Disposing patterns complicate async code, so Microsoft advice is not to Dispose.

Exceptions

An async task may throw either an AggregateException or a TaskCancelledException.

But it is possible to have a void-return to not be captured... and uncaptured exceptions will crash the app when garbage collected.

.Net 4.0 Task Parallel Library

//separate creation from scheduling
//var task1 = new Task<int>(() => int.MaxValue);
//task1.Start();
//preferred
var task = Task.Factory.StartNew(() => int.MaxValue);
 
try
{
    //block with a timeout
    if (!task.Wait(TimeSpan.FromSeconds(1)))
    {
        Debug.WriteLine("It took longer than a second");
    }
    return task.Result;
}
catch (AggregateException exception)
{
    // exception.InnerExceptions can include nested AggregateExceptions
    // so exception.Flatten() to simplify
    exception.Handle(x =>
                         {
                             if (x is OverflowException)
                             {
                                 Console.WriteLine("Overflow handled");
                                 return true;
                             }
                             return false;
                         });
}

Func Results

 
var task = Task<int>.Factory.StartNew(() => 1 + 2);
int result = task.Result; //this blocks- like task.Wait()

Multiple tasks

var tasks = new Task[2]
{
    Task.Factory.StartNew(Work1),
    Task.Factory.StartNew(Work2)
};
 
//Block until all tasks complete.
Task.WaitAll(tasks);

Continuations

var continuationTask = Task.Factory
    .StartNew(() => ReadFile())
    .ContinueWith(x => ReadLines(x.Result));

Also ContinueWhenAll, ContinueWhenAny

Cancellations

MSDN. Pass in a cancellation token and cancel the token source on the main thread.

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
    token.ThrowIfCancellationRequested();
    for (var i = 0; i < 3; i++)
    {
        Thread.Sleep(TimeSpan.FromSeconds(1));
        //raise an OperationCanceledException
        if (token.IsCancellationRequested)
            token.ThrowIfCancellationRequested();
    }
    //pass in the token
}, token);
//cancel it
tokenSource.Cancel();
//run it
try
{
    task.Wait();
}
catch (AggregateException)
{
    //will hit here
}
Console.WriteLine(task.IsCanceled);

Async- await (.net 4.5)

await makes the rest of the method a continuation. You can't use it in catch/finally blocks.
await Task.Run(() => 1 + 2);

//You must also mark lambdas "async" when they include an await...
var result = await Task.Run(async () =>
{
    await Task.Delay(1000);
    return CpuIntensive();
});

An async method may return Task<T>, but the "return" statement is of type T. The compiler rewrites your code. public async Task<bool> IsTrue implements interface bool IsTrue

You can also store and await later (concurrency:)

var task1 = RunAsync();
var task2 = Run2Async();
 
Task.WaitAll(new Task[] { task1, task2 });
//or
await Task.WhenAll(task1, task2);
 
var result1 = task1.Result;
var result2 = task2.Result;

Or, more simply:

var task1 = RunAsync();
var task2 = Run2Async();
//tasks are now running simultaneously
var result1 = await task1; //wait for first task to finish
var result2 = await task2; //wait for second

Prevent reentrancy

You can cache the Task... Note no async/await here.

private static Dictionary<string, Task<string>> _cache =
    new Dictionary<string, Task<string>>();
 
private static Task<string> GetPageAsync(string uri) //no "async"
{
    Task<string> task;
    if (_cache.TryGetValue(uri, out task)) return task;
    //no "await" keyword- set the dictionary value to the task
    return _cache[uri] = new HttpClient().GetStringAsync(uri);
}

Cancellation

You can create a Task with a Task.Delay(timeout) which then fires a cancellationToken. But in .net 4.5 it is simpler to just set the timeout in the CancellationTokenSource ctor.

//timeout of one second
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var get = await new HttpClient().GetAsync(url, cts.Token);
get.EnsureSuccessStatusCode();
var response = await get.Content.ReadAsStringAsync();

Wrap in try/catch(OperationCancelledException) Then cts.Cancel(); to cancel.

NB: WInRT doesn't have tokens, but you can use the extension method .AsTask(token) to turn it into standard .net.

CancellationToken is a struct, so in implementing methods the input argument should get an empty token

private async static Task<string> RunAsync(
    CancellationToken token = default(CancellationToken))

Progress

You can also use Progress<T>.Report(value) for progress reporting.

//create the progress with an Action (eg update UI progress bar)
var progress = new Progress<int>(i => Console.WriteLine(i));
var task1 = RunAsync(progress);

private async static Task<string> RunAsync(IProgress<int> progress,
    CancellationToken token = default(CancellationToken))
{
    for (int i = 0; i < 10; i++)
    {
        await Task.Delay(400);
        progress.Report(i);
    }
    return "Done";
}

Async void

Avoid async void. You can't catch exceptions or wait for their tasks to finish.

Testing

MSTest supports async Task testmethods since VS2012. When using mocks, use Task.FromResult(x)

var moq = new Mock<IService>();
moq.Setup(x => x.Save(It.IsAny<Message>())).Returns(Task.FromResult((int?)1));