c# - Stung by using Linq deferred execution with async/await -


i new async/await , tinkering execute operation on list of objects using list of tasks. used linq generate both list of objects , list of tasks. example below looks little contrived, simplified version of actual code.

i found when code executed shown, after tasks have completed (after await), none of object's properties have been updated, , of tasks still have status of running.

i found eliminating linq deferred execution converting both objects , tasks actual lists via .tolist<>(), code worked expected (objects populated, tasks run completion).

i familiar linq deferred execution i'm confused (isn't) going on in code. i'm making noob mistake async/await...what it?

private class foo {     public datetime { get; set; } }  private void button_click( object sender, eventargs e ) {     populatedates(); }  private async void populatedates() {     var ordinals = new list<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };      var foos = ordinals.select( o => new foo() ); //.tolist();      var tasks = foos.select( f => populatedateasync( f ) ); //.tolist();      await task.whenall( tasks );      var firstnow = foos.elementat( 0 ).now;     var firsttaskstatus = tasks.elementat( 0 ).status; }  private task populatedateasync( foo foo ) {     return task.run( () => populatedate( foo ) ); }  private void populatedate( foo foo ) {     thread.sleep( 2000 );     foo.now = datetime.now; } 

your problem due linq's deferred execution. in particular, task.whenall appropriately waiting tasks complete. however, when call elementat, sequence re-evaluated, creating new foo , task.

so, not work:

var ordinals = new list<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };  var foos = ordinals.select( o => new foo() ); //.tolist();  // first foo, creating it. var first = foos.elementat(0);  // gets *different* foo. creates again. var other = foos.elementat(0);  messagebox.show((first == other).tostring()); // displays "false" 

in general, it's idea "reify" sequence (using toarray or similar) when dealing operations side effects, including starting async operations. task.whenall reify sequence internally, if evaluate again (e.g., elementat), unexpected behavior.


Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -