Fabian's Mix

Mixins, .NET, and more

C# 5: await and ThreadPool.SwitchTo()

with one comment

Last week, I managed to read the 38-page whitepaper explaining the .NET Task-based Asynchronous Pattern in detail. That’s the pattern behind the new C# and VB.NET “async” support everybody is blogging about, for example, Eric Lippert, Alexandra Rusina, or Jon Skeet.

Those blog posts I’ve linked to give good examples on how you can write code orchestrating asynchronous tasks in a very simple, linear fashion. For example, from Eric Lippert’s blog:

async void ArchiveDocuments(List<Url> urls)
Task archive = null;
  for(int i = 0; i < urls.Count; ++i)
    var document = await FetchAsync(urls[i]);
    if (archive != null)
      await archive;
    archive = ArchiveAsync(document);

This code starts tasks that asynchronously (“without blocking the application”) fetch documents and archive them, with the coordination between the tasks written using an ordinary for loop and an if clause. This is cool because with previous asynchronous patterns in .NET, ie., the Begin…/End… Asynchronous Programming Model, or the Event-Based Asynchronous Pattern (heavily used by Silverlight applications), coordination of asynchronous tasks is quite cumbersome, and cannot be written in such a linear manner.

With the Task-based Asynchronous Pattern, the term asynchronous does not necessarily mean multithreaded – whether the FetchAsync and ArchiveAsync methods run their work on a background thread, in a separate process, in the cloud, or via some esoteric operating system mechanism does not matter for the orchestration code. The Task-based Asynchronous Pattern uses the .NET synchronization context and task scheduler mechanisms to ensure the coordination method is resumed on the correct thread when an awaited task has finished performing its work; it doesn’t care how (or on which thread) exactly the work was performed.

There is an interesting consequence of this, which I haven’t seen anyone blog about yet: you can also await pseudo-tasks that do not schedule work, but only switch to another context!

Here is an example from the aforementioned whitepaper:

public async void button1_Click(object sender, EventArgs e)
  string text = txtInput.Text;

  await ThreadPool.SwitchTo(); // jump to the ThreadPool

  string result = ComputeOutput(text);
  string finalResult = ProcessOutput(result);

  await txtOutput.Dispatcher.SwitchTo(); // jump to the TextBox’s thread
  txtOutput.Text = finalResult;

I like this a lot! Without await, you would use the ThreadPool.QueueUserWorkItem() method, passing in a continuation delegate that first performs the expensive computations, then calls Dispatcher.BeginInvoke(), passing in a continuation delegate that sets the text box text:

public async void button1_Click(object sender, EventArgs e)
  string text = txtInput.Text;

  ThreadPool.QueueUserWorkItem (() => {
      string result = ComputeOutput(text);
      string finalResult = ProcessOutput(result);

      txtOutput.Dispatcher.BeginInvoke ((Action) () => txtOutput.Text = finalResult);

Of course, await more or less uses the same continuation concepts under the hoods. But code using await is so much easier to read than explicitly wiring up the delegates.

Asynchrony is one of these situations where syntactic sugar matters a lot, I think.

Written by Fabian

November 8th, 2010 at 9:29 am

Posted in .NET development

One Response to 'C# 5: await and ThreadPool.SwitchTo()'

Subscribe to comments with RSS

  1. I totally missed this – this is great.

    When I first read this I thought back to the old PDP-10/TOPS-20 computer/OS. You could set up a job on the command line, configure it, etc., then suspend it, type a command, and core would be dumpped to a file to be later read-back in in a batch environment and off it would go.

    Which leads me to wonder about this feature… When you combine it with a complete AST from the compiler (the note at the end of the PDC talk about the C# compiler services) I can’t help but wonder if this is where Volta will show up again. No reason that you could use the compiler to re-write the lambda that is generated in jscript, put a subt funciton in that sends everything accross the wire, etc., etc. I’m not 100% sure how useful that is, but that would be very cool! 🙂

    Perhaps, it might even be possible to "suspect" a programs operation… So the code hits a swich to, stops executing for a day (or two), and then resumes – sort of like Windows Workflow, but now automated? That is an awful lot of state (esp when it comes to db connections), but it could be that this gives you the tools to do that.

    I can also think other things like that that would be useful perhaps. One language to rule them all, and then a few translators…

    Gordon Watts

    20 Dec 10 at 15:58

Leave a Reply