Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Stephen Cleary

Stephen Cleary Stephen_​Cleary

Niner since 2011

  • Azure Queues 102 -  Background Queue Processing with Mark Simms

    Thanks for the video, guys! Queues and separation of backend processing is an important subject that a lot of developers don't see the need for, and I'm sure these videos will be helpful!

    I do have a few corrections regarding the async/await usage (mainly talking to others who are going to be watching this video):

    First, keep in mind that the threading situation is very different in the front-end (WebAPI) in the Post method, and in the back-end (worker role). In WebAPI, you're in ASP.NET; whereas the worker role is just a single thread.

    My comments:
    - An async WebAPI method should return Task or Task<T>, not void. If you actually call this code, ASP.NET will catch this mistake and throw an InvalidOperationException with the rather confusing error message "An asynchronous module or handler completed while an asynchronous operation was still pending." The fix is to make Post into an async Task method instead of async void.
    - It's not actually "fire and forget". ASP.NET keeps track of all asynchronous methods that have not yet completed. So, even though your code doesn't have to handle it, ASP.NET does. To be clear, "fire and forget" is extremely dangerous on ASP.NET and most server scenarios.
    - In the ASP.NET threading model, you don't want to call Wait on a Task. This will immediately negate all the scalability benefits of async/await, among other problems. If you need to apply a timeout, use cancellation, as such:

    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
    await queue.AddMessageAsync(msg, cts.Token);

    - In the worker role thread, you can use Wait. Although, the code "queue.CreateIfNotExistsAsync().Wait()" is not doing anything more than "queue.CreateIfNotExists()" would.
    - The video made a good point that you can't make a worker role Run method async. This is a common mistake.
    - When you create a new asynchronous method (e.g., DoStuff), you should default the return type to Task or Task<T>, not void. Async void methods cause lots of problems.
    - Task.Factory.StartNew does not understand async methods, so the LongRunning option actually doesn't do anything. It's better to just use Task.Run, which was designed for use with async methods.

    For more information on general async best practices:
    http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
    http://blogs.msdn.com/b/lucian/archive/2013/11/23/talk-mvp-summit-async-best-practices.aspx
    and StartNew in particular:
    http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
    http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html

  • Building an MVVM-Based Architecture That Works for Windows Store Apps

    I enjoyed the session, but I must disagree with your assertion that async/await is more complex than callbacks.

    First, there is an exception in the Task: Task.Exception. Conceptually, the Task<T> type can represent either success or error; it has both a Result and Exception property, which are roughly analogous to the two parameters for your callback.

    Secondly, an implementation of IProgress<T> is already provided (Progress<T>), which you can instantiate with a delegate as such: "new Progress<int>(value => { ... })". In an MVVM app there's no need to create your own.

    Those are the only real drawbacks to async/await that you mentioned. However, async/await also has several advantages over callbacks:

    1. You mentioned one drawback to chains of asynchronous operations: the lambda nesting can get unwieldy. Await avoids this completely.
    2. Another thing you mentioned is that it can be easy to accidentally ignore exceptions in callback code. The Task<T> type prevents this by encapsulating the result.
    3. Await and Progress<T> both use SynchronizationContext automatically in an intelligent way. This makes any kind of thread marshaling or dispatcher service completely unnecessary, cleaning up service/VM code. 
    4. Error handling is easier. With callbacks, exceptions must be propagated explicitly. Await will naturally propagate them, keeping the original exception type and call stack even if the thread context changed. This is quite difficult to do yourself with portable code.
    5. Await makes more complex asynchronous operations much easier to deal with. E.g., retrying on error, or doing multiple operations at once. With callbacks, these kinds of operations quickly become difficult and commonly require actual callback methods instead of lambdas. With async/await (plus TaskEx.WhenAll / TaskEx.WhenAny), they're quite easy to do.
  • Immo Landwerth and Andrew Arnott: Inside Immutable Collections

    Thanks for the great video, guys! It's nice to know the underlying data structures.

    Just one question (for the interviewer): how is async being overused?

           -Steve

  • Easy Asynchrony with C#: No More Callbacks!

    @KarlZ: You can unit test asynchronous code in VS2012 with MSTest or xUnit by declaring your unit tests as "async Task" instead of "void".

  • Async in ASP.NET

    Thanks, guys! Great content!

    In particular, thanks for not just showing "what works" but also the pitfalls. Smiley

    Just a couple of notes:

    1. WhenAll will actually return the results of those tasks. So you can replace:
          await Task.WhenAll(results);
          return results.Select(t => t.Result);
      with:
          return await Task.WhenAll(results);
    2. I recommend that async/await users never use Task.Result (for the reasons you mentioned). There's a bit of overhead to use "await task" instead of "task.Result" on a completed Task, but the code is more obviously correct.

     

           -Steve

  • The zen of async: Best practices for best performance

    Awesome talk, Stephen! Wish I could have been there in person!

    Thank you in particular for going "deep".

    One quick question re your demo where Wait causes a deadlock: is that a change in behavior? I haven't tried it, but from my understanding of http://blogs.msdn.com/b/pfxteam/archive/2009/10/15/9907713.aspx, I would expect Wait to run the task inline in this scenario.