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

Comments

Lucian Wischik ljw1004
  • Tip 4: Async Library Methods Shouldn't Lie

    @Joao, thanks for the pointer. I think that MSDN page has poor guidance. I'll contact the authors of it.

  • Tip 4: Async Library Methods Shouldn't Lie

    @squizfloats - You've got the right idea. This is a situation where the overall API design is forcing you to have an async signature, even though your method itself isn't async in its implementation.

    Please watch the next video in the series. That discusses EXACTLY this case. Actually it discusses it in the guise of "MemoryStream". Obviously Stream has to have async APIs since most streams (disk, network, ...) are asynchronous in nature. But when you come to implement MemoryStream, it has no natural async implementation. And so it uses Task.FromResult exactly as you described.

    The video talks about several useful micro-optimizations specifically for this case. Worth considering.

  • Creating Async Libraries That Are Modular, Reusable and Fast, in Microsoft Visual C# and Visual Basic

    I uploaded the source code for this session here: http://blogs.msdn.com/b/lucian/archive/2013/06/28/talk-the-complete-async-three-talks-from-teched-europe-2013.aspx

  • Three Essential Tips for Using Async in Microsoft Visual C# and Visual Basic

    I uploaded the source code for this session here: http://blogs.msdn.com/b/lucian/archive/2013/06/28/talk-the-complete-async-three-talks-from-teched-europe-2013.aspx

  • Easy Async for Windows Store Apps in Microsoft Visual C# and Microsoft Visual Basic

    I uploaded the source code for this session here: http://blogs.msdn.com/b/lucian/archive/2013/06/28/talk-the-complete-async-three-talks-from-teched-europe-2013.aspx

  • Tip 2: Distinguish CPU-Bound work from IO-bound work

    @Srini, we also saw this within Visual Studio itself. We wanted to write the new features of the product using async. But they still had to speak to the older synchronous components within VS. The result was that a lot of our async methods had to make blocking calls to those components.

    Result: thread starvation, because we were using all available threads, and the TPL was only giving us one additional thread a second.

     

    Fix: to fix this we've been systematically spreading the "async virus" throughout those components, making them all use async from top to bottom, so that we don't starve the threadpool.

  • Tip 3: Wrap events up in Task-returning APIs and await them

    In the RX sample, where I wrote "accel.ReadingChangedObservable()", it was actually just a call to Observable.FromEventPattern(accel, ...). I omitted the lambdas to keep the code simpler.

    So what you're talking about as an "API" would merely be the call to Observable.FromEventPattern. And what you're saying is that I could have used "Observable.FromEventPattern" identically in both the async version and the RX version. Is that right?

  • Tip 3: Wrap events up in Task-returning APIs and await them

    I'm not sure where "API" is a question? We're already given an event-based API from the accelerometer - I reckon that events will be with us for a long time. The question is (1) whether Shake should be exposed as an event or an IObservable, (2) whether we should implement our logic using RX combinators or language combinators.

  • Tip 3: Wrap events up in Task-returning APIs and await them

    Hi wkempf! You say "IObservable is the correct solution." That might be true, but it's by no means obvious, and requires supporting evidence. That supporting evidence would be in the form of example problems, to see which approach winds up simpler, more maintanable, and more debuggable.

    I'd like to see examples! How about you try writing the apple-game into RX and post here?

    Here's another example. I picked "shake detection" since that's been a common RX example. Let's compare them side by side:

    // Shake detection using async (from a stream of Accelerometer.ReadingChangedEventArgs)
    
    public async void StartShakeWatcher(Accelerometer accel) {
        var t = DateTime.Now;
        while (true) {
            var e = await accel.ReadingChangedAsync();
            if (Math.Pow(e.AccelerationX, 2) + Math.Pow(e.AccelerationY, 2) < 1.1) continue;
            if ((DateTime.Now - t).Milliseconds < 200) Shake(this, null);
            t = DateTime.Now;
        }
    }
    
    
    // Shake detection using RX (from a stream of Accelerometer.ReadingChangedEventArgs)
    
    public static IObservable<Event<AccelerometerArgs>> GetShakeObserver(Accelerometer accel) {
        return accel.ReadingChangedObservable()
               .Where(e => (Math.Pow(e.EventArgs.Reading.AccelerationX,2) +
                            Math.Pow(e.EventArgs.Reading.AccelerationY,2) > 1.1))
               .TimeInterval()
               .Where(k => k.Interval.Milliseconds < 200)
               .Select(k => k.Value);
    }

    And here's how you'd consume the two:

    Private Sub OnShake() Handles ShakeWatcher.Shake
        ' ...
    End Sub
    
    Overrides Sub OnNavigatedTo()
        GetShakeObserver().Subscribe(Sub() ...)
    End Sub
    

    I think this one's a wash. Same number of lines of code. The async one allows single-step debugging and doesn't involve lambdas. The RX one is marginally more efficient.

     

    In cases where you have streams of events and need to apply advanced combinators to them, especially when combing streams in complex ways, then RX is unquestionably the best solution. But where you're just doing orchestration of a UI app like here? then it's not so clear.

     

  • Tip 1: Async void is for top-level event-handlers only

    Hi SonOfSam! Good question. Let's look at a concrete example.

    Sub f(a As Action)
      a()
      Console.WriteLine("done")
    End Sub
    
    f(Async Function()
        Await Task.Delay(100)
        Console.WriteLine("almost-done")
    End Function)


    In VB, when you write a lambda as "Async Function", then it will always be a Task-returning async. When you write it as "Async Sub" then it will always be a void-returning async.

    But VB has a feature called "delegate relaxation". The compiler realizes that it would be type-safe to just automatically drop the return value of a lambda if needed.

    Well, it would be type-safe, but it's not what we wanted. In this case when the compiler drops the returned Task, then (1) the caller "f" can't know when the lambda has finished, and (2) any exceptions caused by the lambda that were stored in the returned Task will be completely lost to everyone.

    So the guidance for VB is this: when you pass an Async Function lambda, you should verify that the method you're calling does indeed accept Func(Of Task) or some other Task-returning delegate. Just like in C#.


    (Incidentally, if you try to pass an Async Sub lambda to a function, where an Async Function lambda would also have worked, you're almost certainly doing the wrong thing. In this case the compiler gives a warning).