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

Mads Torgersen: Inside C# Async

Download

Right click “Save as…”

Mads Torgersen, C# specification lead, describes the new C# features to improve asynchronous development. You can get an early look at this new async programming model, available as the Async CTP, today!

Tags:

Follow the Discussion

  • RafaelRafael

    If the implementation of the await feature is tied to the Task type, then why is it necessary to declare the method as async? In the familiar case of iterators the feature was dependent on the type alone (IEnumerable). Granted, because IEnumerable is an interface, it could be argued that in the case of async the keyword would accommodate hypothetical future types which wouldn't share the Task interface; but then why was not an interface type adopted for the async feature - IObservable, for instance - in the first place?
    This kind of feels like too much given what we already know about previous language features. Specifically, what I would expect is to have an implementation of the familiar iterator syntax over an interface abstraction to asynchronous programming consuming the Task type behind the scenes. I'll admit that is fairly idealistic, but, as we know, every bit beyond that is potential bloat.

  • shaggygishaggygi

    This is good stuff, but I'm little confused on an idea where this may be used...
    Example:  Using Data Received event for incoming data on a Serial Port ( or a virtual USB COM port ).  Would it be possible to have a Task to receive data from the port ( one byte at a time ) and build a data packet.  Once the packet is complete, it validates and parses the data and then returns the results to the UI for data binding to the UI's controls.  Would this be a useful way to use this approach?
    If this is true, then could you have Tasks work with other Task?  Example: I have a main Task that is in control of sending/receiving data from the Serial Port.  I then have many Tasks that can call the main Task to send/receive specific data for the calling Task.  Once the main Task calls back to the calling Task, the calling Task can then send the specifc results back to the UI for binding.
    Again, not sure if this would be appropriate approach, but seems like it would be nice for a data protocol stack.  If so, this would be great.  Thanks in advance.

  • SamSam

    I'm with Rafael. Here's my immediate reaction and suggestions:
    Drop the async keyword.
    Allow IObservable as a third option to void and Task. yield return would return a value to the IObservable yield break would kill it.
    Change var result = await T; to yeild await T; var result = T.Result;
    Add foreach syntax for IObservable for async methods. IE. foreach(int i in SomeIOberservableOfInt) { DoStuff(i); } which works asynchronously as well.
    That would be more coherent and much more awesome.
    I was concerned how Eric and Rx was dropped abruptly. I think it's game changer and deserves more time and love.

  • KrisKris

    Is it just me, or does Mads resemble a young Harrison Ford?  Get him an accent coach, and we could cast him as a young Han Solo in a future Star Wars movie or TV show... Professor Jones?

  • I'm with Kris.

    Professor Jones, totally.

  • diryboydiryboy

    [quote]
    6 hours ago
    If the implementation of the await feature is tied to the Task type,... [/quote]
    Hi, it's not tied to Task type, I downloaded the spec here http://go.microsoft.com/fwlink/?LinkId=204845 and it says
    [quote]
    C# does not dictate a specific type for the representation of tasks that are await’ed, as long as they satisfy a certain pattern. The types Task and Task<T> satisfy this pattern, and will be used in subsequent examples.
    [quote]

  • Very cool. I do mostly web development & SharePoint development, so I am wondering if this will be useful to me at all.

  • LukaszLukasz

    @diryboy:
    Not true.  From the document you link to: "An asynchronous function in C# must either return void or one of the types Task or Task<T>.".  The flexibility is on what object can be "await"-ed for, but not on the return type of an "async" method.
    Constraining the return type to Task<T> means that an asynchronous method returning a collection has to return the whole collection once it is done;  it cannot return elements one-by-one as they arrive (which would be possible in the IObservable<T> pattern).

  • devindevin

    I dont get the point of the async keyword.  Why not just allow the await keyword anytime the method returns Task<T>, just like interators can yield return on any method that returns an IEnumerable<T>.

  • This is great talk from Mads!   

     

  • Very nice stuff.

    Charles, you should get Mads together with Brian Beckerman/Bart de Smet/Eric Meier and do "Monads & Async jam" - it would be no fun if there were no monads Smiley

  • CharlesCharles Welcome Change

    , Kyrae wrote

    Very nice stuff.

    Charles, you should get Mads together with Brian Beckerman/Bart de Smet/Eric Meier and do "Monads & Async jam" - it would be no fun if there were no monads Smiley

    Smiley

    I do want to get Mads on 9 more often. He's a great conversationalist! Would be great to get Brian and Erik's perspective on this new language feature. Actually, you can get a glimpse of this (in terms of Erik) in the C9 Live piece with Erik and Wolfram Schulte. It's available at http://microsoftpdc.com (check out the C9 Live on-demand stuff in the player).

    C

  • bbattahbbattah

    Very interesting.  I must not have the model in my head correctly as I am still curious about the idea that no back-ground thread is ever consumed.  How does the returned "Task" from an async method call ever change state to "completed" if there is no code execution (thread) involved?  Similarly if I choose to "await" a Task, upon what thread does the code run that inspects the SynchronizationContext and initiates the supplied call-back into the state machine?

  • Eric AguiarHeavens​Revenge Know Thyself

    Well when I think of Acync, I think of asynchronously pushing tasks waiting to be done on to a core which is the one next in line, which would also be specific per machine. I'm no C# coder but heres a Pseudo-C# way I think I could describe what I'm thinking.

    class DispatchThreadsAsync
    {
      static void Main()
        {
          const int maxThreadCount = Enviroment.ProcessorCount;
          var workToBeDone  = new List<Task>();
          int threadNumber = 1;
          while (thread < CONCURRENCY && thread != 0)
          {
            foreach (int workItem in workToBeDone)
            {
              async workToBeDone.Add(ScheduleNextThreadAsync( threadNumber , workItem ));
            }
            threadNumber = thread.nextAvailableThread();
          }
       }
    }

    So I mean that to capture a dynamically scheduled loop method thingy that schedules un-even workloads as threads onto cores which become available. Asynchronously creating/reusing/receiving thread tasks per work item in a work queue as long as work is available.

    To me that would be a cool way to dynamically dispatch newly created work items and threads.  And I'd suggest that the C# team see if this type of method for creating tasks of work to be done could be made into a nice little industrial-strength official C# 5.0 asynchronous task method Smiley

    As I said im no C# coder but I tried my best to pseudo-C# my point across by what I think would be a good abstraction Smiley unless it already exists of course and I haven't looked hard enough Tongue Out

  • So maybe I'm missing something, but is there a way to create little pieces of asynchronous work without having to pull everything out of the method into its own async method? E.g. to use the WhenAll example... So if you start with something like

    public async Task<List<Result>> GetResults()
    {
        var results = new List<Result>();
        foreach (var url in urls )
        {
             UnprocessedResult r = await DownloadResult(url);
             results.Add( processResult(r) );
        }
        return results;
    } 

     

    But then to get the improved parallelism that they talk about in the video, you want to use WhenAll, so you do this:

    public async Task<List<Result>> GetResults()
    {
        var results = new List<Result>();
        var tasks = new List<Task<result>>();
        foreach (var url in urls )
        {
             tasks.Add (DownloadResult(url));
        }
        await Task.WhenAll(tasks);
        foreach (var t in tasks)
        {
             results.Add( processResult(t.Result) );
         }
        return results;
    } 

     

    The problem is the fact that we have to do the "continuation" of each task in a separate loop. One way of fixing this is to move the loop body out into its own async method which awaits DownloadResult and then processes it afterwards. Then the main function can just WaitAll on *those* tasks. But having to create a brand new method for tiny "post-async-fixups" is onerous. It would be cool if we could just create async lambdas, which we then call immediately, which then returns a task with the body inside it. E.g.:

    public async Task<List<Result>> GetResults()
    {
        var results = new List<Result>();
        var tasks = new List<Task<UnprocessedResult>>();
    
        foreach (var url in urls )
        {
             // notice async lambda, that gets called immediately
             tasks.Add( async () => {
                     var r = await DownloadResult(url);
                    results.Add( processResult( r ) );
             }() );        
        }
    
        await Task.WhenAll( tasks );
        return results;
    } 

    You can't call a lambda like that, so even with async lambdas it would be ugly:

    public async Task<List<Result>> GetResults()
    {
        var results = new List<Result>();
        var tasks = new List<Task<UnprocessedResult>>();
    
        foreach (var url in urls )
        {
             // notice async lambda, that gets called immediately
             Func<Task<UnprocessedResult>> f = async () => {
                     var r = await DownloadResult(url);
                    results.Add( processResult( r ) );
             };
             tasks.Add( f() );        
        }
    
        await Task.WhenAll( tasks );
        return results;
    }

    Perhaps an alternate syntax which does the above would be in order?

    public async Task<List<Result>> GetResults()
    {
        var results = new List<Result>();
        var tasks = new List<Task<UnprocessedResult>>();
    
        foreach (var url in urls )
        {
             tasks.Add( async {
                     var r = await DownloadResult(url);
                    results.Add( processResult( r ) );
             });        
        }
    
        await Task.WhenAll( tasks );
        return results;
    }

    Where "async{ ...}" just whips up a simple local Task that does the stuff in the body.

  • Eric LippertEric Lippert

    Lots of good questions here. However, Channel 9 comments is not a great forum for Q&A. Please post your additional questions to:
    http://social.msdn.microsoft.com/Forums/en-US/async/threads
    Regarding the question "why do we require the async modifier?" please see my answer here:
    http://blogs.msdn.com/b/ericlippert/archive/2010/11/11/whither-async.aspx
    > How does the returned "Task" from an async method call ever change state to "completed" if there is no code execution (thread) involved?"
    You don't need multiple threads to do more than one task. Look at it this way. You (a thread) run a sandwich shop (a service). Two people (clients of the service) come in and sit at different tables (enqueue themselves onto a work queue). A transaction consists of two tasks that must happen in order: take a sandwich request, and make the sandwich. Therefore there are going to be four tasks: two orders to take and two sandwiches to make.
    You could do both transactions synchronously: take the order of the first customer, make their sandwich, take the order of the second customer, make their sandwich. Or you can do it asynchronously: you take the order of one customer, then take the order of the second customer, then resume the first transaction: make the first sandwich. Then resume the second transaction: make the second sandwich. Each task signals its completion when it is done, and the single thread then does the next task in the work queue. No multithreading is necessary to make two sandwiches *after* both orders are taken. You don't need two sandwich makers, or one waiter and one sandwich maker. You only need one thread.
    Single-threaded asynchrony is simply about breaking up work into small pieces and then choosing a different order to do each part of the transaction, rather than doing all the work associated with one transaction before starting the next. You don't need a dozen waiters  to serve a dozen tables ; you need one waiter who can split up the workflow associated with each table into chunks that are small and easily reordered so that no one table has to wait a long time for their next unit of work to be processed.
    Of course, you *can* use concurrency with asynchrony, but asynchrony does not *require* concurrency.
    > if I choose to "await" a Task, upon what thread does the code run that inspects the SynchronizationContext and initiates the supplied call-back into the state machine?
    That depends on the details of the task. Suppose you have a UI thread and a worker thread. If the task is awaited on the UI thread and runs on the worker thread then the task will typically signal its completion by posting a message from the worker thread to the UI thread. The completion then runs on the UI thread when the UI thread pumps messages.
     

  • Eric LippertEric Lippert

    Apparently all my paragraph breaks disappeared there. Weird. I hope that is legible.

  • Yury SerdyukYury Serdyuk

    Hi !
    Can you explain to me why we need await keyword in
    await Task.WhenAll(tasks);
    expression ?
    At first, WhenAll method returns nothing, so what task we await ?
    Then, WhenAll wait a completion of all tasks yet, so why we need extra await statement here?
     

  • Yury SerdyukYury Serdyuk

    Again all paragraph breaks disappeared. Sorry ...

  • Harrison FordHarrison Ford

    Sorry, couldn't resist. Mads Torgersen here.
    Yury: when you call WhenAll it immediately returns a Task representing the completion of all the Tasks you passed to it. When you await the returned Task you know that all those original Tasks have completed.
    This is very useful for orchestrating "parallel" Tasks; e.g. multiple requests on the internet.
    (Apologies in advance if my paragraph breaks disappear - I assure you they were there when I typed it!)
    Mads

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.