Announcing the Async CTP for Visual Basic (and also Iterators!)

Announcing the Async CTP for Visual Basic (and also Iterators!)

Rate This
  • Comments 13

We're very happy to announce today the Async CTP for Visual Basic and C#.

Asynchronous programming is something that helps make your UI more responsive, especially in applications that interact with databases or network or disk. It's also used to make ASP servers scale better. And it's the natural way to program in Silverlight.

Until now, asynchronous programming has also been prohibitively hard, "not worth the investment"-hard. But with the Async CTP we've made asynchronous programming easy enough that developers should routinely consider asynchrony for most of their applications.

Async is a true "parity" feature between VB and C#. We had the same designers develop it in VB and C# at the same time, and the same developers implement the feature for both compilers, and even the same unit tests for both. The end result is a feature that's keyword-for-keyword identical in both languages (and probably bug-for-bug compatible in the CTP...)

We're also very happy to announce that iterators are coming to VB, and are included in the Async CTP! That's because async and iterators are deeply related (and inside the compiler they're implemented with 99% the same codebase). We'll write further posts about iterators.

 

A real-world example of asynchrony

"A waiter's job is to wait on a table until the patrons have finished their meal.
If you want to serve two tables concurrently, you must hire two waiters."

Q. That sentence is obviously wrong. What is the flaw?

A. You don't need two waiters! A single waiter can easily serve two tables concurrently, just by switching between them.

Why am I talking about waiters? Think of the waiter as a thread, and the table as a method that it executes. Traditionally, when you wanted to do two things at the same time (e.g. keep the UI responsive while downloading a file) then you'd have used two threads. But it's inefficient to create extra threads (hire waiters), and you had to jump through hoops to update the UI from the background thread (make sure that the waiters don't conflict).

 

Let's see what the waiter really does, written using VB Async:

Async Function WaitOnTablesAsync() As System.Threading.Tasks.Task(Of Decimal)
    Dim takings As Decimal = 0D
    While Not TimeToGoHome
        DeliverMenus()
        Await GetOrdersAsync()
        Await WaitForKitchenAsync()
        GetFoodFromKitchen()
        GiveFoodToPatrons()
        Await WaitForPatronsToFinish()
        takings += Await GetPayment()
    End While
    Return takings
End Function

Async
Sub Button1_Click() Handles Button1.Click
    Dim takings As Decimal = Await WaitOnTablesAsync()
    MessageBox.Show("Shift finished; took {0}", takings)
End Sub

 

Things to notice in this code:

  1. At each Await keyword, the waiter (thread) suspends execution of the method he's currently in. He can go off to do other work, like responding to UI events. When the thing he's awaiting has completed, and he's free, then he resumes his method.
  2. The WaitOnTablesAsync function has the modifier Async. This modifier allows it to have Await expressions inside.
  3. WaitOnTablesAsync returns a Task(Of Decimal). It actually returns this task promptly at its first Await expression. The task is a placeholder for the work and return value that the waiter will eventually return when he's finished.
  4. Button1_Click can also Await that Task. Once again, when this task has completed, then Button1_Click can resume and it shows the message-box.

 

What is asynchrony? (and what isn't it?)

Asynchrony means "not [a-] at the same time [-synchronous]". It means that the the async function gives back a Task immediately, but that Task is just a placeholder: the real result will be delivered sometime later.

Asynchrony does not mean "running on a background thread". Running on a background thread is one way to implement asynchrony, but it's not the only way, and it's often not the best way.

There are no additional threads in the above code. There's only a single thread, the UI thread. The Async modifier does not create additional threads. All it does is mark a method as asynchronous (and allow it to Await). If you want to do work on a background thread, you will have to do so explicitly using TaskEx.Run:

Await TaskEx.Run(Sub()
                     ' long-running CPU work can go here
                 End Sub)

 

Asynchrony in practice

I read this on a blog recently. It also has a subtle flaw. What is the flaw?

"A good practice in creating responsive applications is to make sure your main UI thread does the minimum amount of work. Any potentially long task that may hang your application should be handled in a different thread. Typical examples of such tasks are network operations, which involve unpredictable delays."

Hint:

Private Async Sub Button1_Click() Handles Button1.Click
    Dim url = "http://blogs.msdn.com/lucian/rss.aspx"
    Dim wc As New WebClient
    Dim result As String = Await wc.DownloadStringTaskAsync(url)
    Dim rss As XDocument = XDocument.Parse(result)
    MessageBox.Show(rss.DescendantNodes.Count)
End
Sub

 

If you can spot the flaw in the above sentence, or if you can follow this code and understand why it allows the UI to stay responsive, then you're ready to start coding with the Async CTP!

 

There's a lot more to read on the subject of asynchrony:

 

Leave a Comment
  • Please add 8 and 1 and type the answer here:
  • Post
  • Since you say that the Async framework does not use new threads the flaw must be "should be handled in a different thread"

    But, how ASync works? How can it free the UI thread without opening new threads?

  • Eduardo: it seems to be syntactic sugar for the Tasks in TPL, i. e. Task.ContinueWith. They can use the thread pool, overlapped i/o or whatever else the programmer might want; read more on tasks if you're interested.

  • Theres nothing stopping you from executing these async functions on background threads if you so chose.   But consider the function could be blocking as it is CPU bound or blocking because of some other latency such as waiting to retrieve stuff from a remote data source.    In one of these scenarios spinning off a thread may help in the other it probably would not.    If you think on one that is waiting for remote data - why should the UI thread be blocking when the CPU is doing nothing.   The concept of async is more orchestrating the activities - not specifically assigning to alternate threads.    If you want to run things on other threads then its easy to do.

  • Will this be added to silverlight as well?

  • @Solmead: the Async CTP works with Silverlight, and many of the samples are Silverlight samples. We're working with the Silverlight team to figure out what is the best way to get it into Silverlight.

    @Skytribe, I think that's the best answer to the puzzle. It's true that you shouldn't do WORK on the UI thread. But merely sitting around idle waiting for a network response -- this doesn't really count as work.

  • How do you wait on multiple possible asychronous events such as waiting on 4 different asychronous file writes to complete?

    Is there a way to have a timetime time specified for a wait?

  • Waiting on several different asynchronous file-writes to complete:

    Using stream1 As New StreamWriter("a.txt"),

       stream2 As New StreamWriter("b.txt")

       ' We'll launch two concurrent tasks in parallel

       Dim task1 = stream1.WriteAsync("hello")

       Dim task2 = stream2.WriteAsync("world")

       ' and wait for them both to complete

       Await TaskEx.WhenAll(task1, task2)

    End Using

    Timeframe specified for a wait -- this one up to two seconds:

    Await Task.WhenAny(task1, TaskEx.Delay(2000))

    Timeframe specified for cancellation:

    cts = New CancellationTokenSource()

    cts.CancelAfter(2000)

    Dim s = New WebClient().DownloadStringTaskAsync("http://a.com", cts.Token)

  • How do you know which of the multiple tasks completed?

  • How does System.Threading.Timer Callbacks fit into this?

    What is the easiest way to get the timer's callback in the UI thread?

    I use System.Threading.Timer excessively for both periodic ticks, timeout dedection as well as fire&forget scenarios. My callback handlers sometimes have dozens of lines, trigger other timers or work recursively...

  • Do you think that it's ok to use the Async framework to wait for the user to complete a task?

    i.e.:

    Private Async Sub EditButton_Click() Handles EditButton.Click

       CurrentPage.enabled = false

       Dim result As Integer = Await EditCustomer( CurrentCustomer )

       If result <> 0 then

          CurrentCustomer.Save()

       end if

       CurrentPage.enabled = true

    End Sub

  • Hi All,

    I wanted to make sure everyone is aware of the Async CTP Forum we've set up on MSDN:

    social.msdn.microsoft.com/.../threads

    We are managing Q&A on the release there, and would greatly appreciate if you can post your question on the forum to ensure a timely response.

    Thanks!

    Lisa Feigenbaum

    Lisa (dot) Feigenbaum (at) microsoft (dot) com

    Visual Studio Community Program Manager

  • 1. There are no words to express our gratitude for bringing Iterator and Yield into VB!

    2. I really find it a bit difficult to understand what's new behind Async CTP. What's there that cannot be accomplished with:

           Task.Factory.StartNew(

               Sub()

                   ' Time consuming operation here.

               End Sub).ContinueWith(

               Sub(t)

                   ' Synchronous continuation here.

               End Sub, TaskScheduler.FromCurrentSynchronizationContext())

    I agree that integrating asynchronous programming as a language feature is a benefit and makes code more appealing. But isn't Parallelism and Tasks API, as introduced in .NET 4 and shown in the example above, quite new to be put aside so fast? Wouldn't then be 2 ways of doing the same thing? Wouldn't that lead the current API being soon obsolete? It's been several months now that I'm rewriting old code to take benefit of the new features in .NET 4, and now this comes.

    3. Saying that this new feature involves no additional threads, is quite misleading. The task you wait for when using Await, still needs to be a background operation or else there's no need to use Await. If for example the implementation of WaitForKitchenAsync from your example above includes no other Await inside it or in any case, it simply includes synchronous operations, then the UI would still hang. Actually there are "fire and forget" cases when working in WPF like I do, where Dispatcher.BeginInvoke() with an appropriate DispatcherPriority would better do the job while really assuring thread affinity.

    4. How are all these new features going to be released? Is there going to be a .NET 4 SP1 and VS2010 SP1 including these features and when? Referencing AsyncCTPLibrary.dll is an issue when developing redistributable class libraries.

    Thank You.

  • Does anyone know - will this work with Silverlight Apps?  This would make working with WCF SO SO SO much easier from SL.

Page 1 of 1 (13 items)