[{"data":1,"prerenderedAt":330},["ShallowReactive",2],{"post-\u002Freactive-extensions-part5-awaiting-observables\u002F":3},{"id":4,"title":5,"author":6,"body":7,"comments":284,"date":310,"dateModified":311,"description":312,"extension":313,"headings":314,"heroImage":319,"meta":320,"path":43,"permalink":43,"published":321,"stem":322,"tags":323,"timeToRead":329},"posts\u002Fposts\u002F2014\u002Freactive-extensions-part5-awaiting-observables\u002Findex.md","Reactive Extensions (Rx) - Part 5 - Awaiting Observables","Muhammad Rehan Saeed",{"type":8,"value":9,"toc":281},"minimark",[10,63,72,94,105,112,130,151,161,164,184,195,198,201,215,218,237,247,250,257,268,274,277],[11,12,13,21,27,33,39,45,51,57],"ol",{},[14,15,16],"li",{},[17,18,20],"a",{"href":19},"\u002Freactive-extensions-part1-replacing-events\u002F","Reactive Extensions (Rx) - Replacing C# Events",[14,22,23],{},[17,24,26],{"href":25},"\u002Freactive-extensions-part2-wrapping-events\u002F","Reactive Extensions (Rx) - Wrapping C# Events",[14,28,29],{},[17,30,32],{"href":31},"\u002Freactive-extensions-part3-naming-conventions\u002F","Reactive Extensions (Rx) - Naming Conventions",[14,34,35],{},[17,36,38],{"href":37},"\u002Freactive-extensions-part4-replacing-timers\u002F","Reactive Extensions (Rx) - Replacing Timers",[14,40,41],{},[17,42,44],{"href":43},"\u002Freactive-extensions-part5-awaiting-observables\u002F","Reactive Extensions (Rx) - Awaiting Observables",[14,46,47],{},[17,48,50],{"href":49},"\u002Freactive-extensions-part6-task-toobservable\u002F","Reactive Extensions (Rx) - Task ToObservable",[14,52,53],{},[17,54,56],{"href":55},"\u002Freactive-extensions-part7-sample-events\u002F","Reactive Extensions (Rx) - Sample Events",[14,58,59],{},[17,60,62],{"href":61},"\u002Freactive-extensions-rx-part-8-timeouts\u002F","Reactive Extensions (Rx) - Timeouts",[64,65,66,67,71],"p",{},"So I've just finished extolling the wonderful virtues of ",[68,69,70],"code",{},"TaskCompletionSource"," with a colleague and thought I'd share the joy more widely. Eventually this will turn into a post about how great Reactive Extensions (Rx) is, I promise.",[73,74,76,70],"h1",{"id":75},"taskcompletionsource",[17,77,80],{"href":78,"aria-hidden":79},"#taskcompletionsource","true",[81,82,88],"svg",{"xmlns":83,"xmlns:xlink":84,"viewBox":85,"version":86,"width":87,"height":87,"aria-hidden":79},"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink","0 0 16 16","1.1",22,[89,90],"path",{"fill":91,"fill-rule":92,"d":93},"currentColor","evenodd","M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z",[64,95,96,104],{},[17,97,70],{"href":98,"rel":99,"target":103},"http:\u002F\u002Fmsdn.microsoft.com\u002Fen-us\u002Flibrary\u002Fdd449174%28v=vs.110%29.aspx",[100,101,102],"nofollow","noopener","noreferrer","_blank"," is a great tool to turn any asynchronous operation which does not follow the Task Parallel Library (TPL) pattern into a Task. The example below is something I've started to do in a few places.",[106,107],"pre",{"className":108,"language":109,"meta":110,"style":110,"html":111},"language-cs shiki shiki-themes light-plus monokai","cs","","\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">public\u003C\u002Fspan>\u003Cspan class=\"sw29p\"> Task\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&lt;\u003C\u002Fspan>\u003Cspan class=\"sJvqV\">bool\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">?&gt; \u003C\u002Fspan>\u003Cspan class=\"sWm5y\">ShowDialog\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">()\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">{\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sw29p\">    TaskCompletionSource\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&lt;\u003C\u002Fspan>\u003Cspan class=\"sJvqV\">bool\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">?&gt; \u003C\u002Fspan>\u003Cspan class=\"sFrd5\">taskCompletionSource\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> new\u003C\u002Fspan>\u003Cspan class=\"sw29p\"> TaskCompletionSource\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&lt;\u003C\u002Fspan>\u003Cspan class=\"sJvqV\">bool\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">?&gt;();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sw29p\">    Window\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> window\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> new\u003C\u002Fspan>\u003Cspan class=\"sw29p\"> MyDialogWindow\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sw29p\">    EventHandler\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> eventHandler\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sMc8R\"> null\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">    eventHandler\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sjLUg\"> \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">        (\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">sender\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">, \u003C\u002Fspan>\u003Cspan class=\"sFrd5\">e\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">) \u003C\u002Fspan>\u003Cspan class=\"snCLD\">=&gt;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">        {\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">            window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">Closed\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> -=\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> eventHandler\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">            taskCompletionSource\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">SetResult\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">(\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">DialogResult\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">);\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">        };\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">    window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">Closed\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> +=\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> eventHandler\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">    window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">Show\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"smL5M\">    return\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> taskCompletionSource\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">Task\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">}\n\u003C\u002Fspan>\u003C\u002Fspan>",[64,113,114,115,118,119,122,123,125,126,129],{},"In the example above we are creating a new window, registering for its ",[68,116,117],{},"Closed"," event and then showing the window. When the window is closed, we de-register from the closed event handler (To avoid a remaining reference to the window, causing a memory leak) and the ",[68,120,121],{},"DialogResult"," of the window is passed to the ",[68,124,70],{}," using the ",[68,127,128],{},"SetResult"," method.",[64,131,132,133,135,136,139,140,143,144,146,147,150],{},"The ",[68,134,70],{}," gives us a nice ",[68,137,138],{},"Task"," object which we can return at the end of the method. When we return the task its status is ",[68,141,142],{},"WaitingForActivation",". Only when the ",[68,145,128],{}," method is called when the window closes, does the tasks status change to ",[68,148,149],{},"RanToCompletion",".",[64,152,153,154,157,158,160],{},"This whole operation has been wrapped up and packaged nicely in a ",[68,155,156],{},"Task\u003Cbool?>"," with a nice bow on top with the help of ",[68,159,70],{},". Now we can call the method and await the results from the method call, thus allowing us to savour the power and simplicity the TPL affords us.",[106,162],{"className":108,"language":109,"meta":110,"style":110,"html":163},"\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">bool\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">? \u003C\u002Fspan>\u003Cspan class=\"sFrd5\">result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sWm5y\"> ShowDialog\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>",[64,165,166,167,169,170,175,176,178,179,150],{},"There are other great ways to use ",[68,168,70],{}," of course. Generally speaking though I have found myself using it to turn an operation where I am waiting for an event into a task. For ",[17,171,174],{"href":172,"rel":173,"target":103},"http:\u002F\u002Fblogs.msdn.com\u002Fb\u002Fpfxteam\u002Farchive\u002F2009\u002F06\u002F02\u002F9685804.aspx",[100,101,102],"more information"," on ",[68,177,70],{}," or the TPL in general I highly recommend reading ",[17,180,183],{"href":181,"rel":182,"target":103},"http:\u002F\u002Fblogs.msdn.com\u002Fb\u002Fpfxteam\u002F",[100,101,102],"Stephen Toub's blog",[73,185,187,194],{"id":186},"awaiting-observables",[17,188,190],{"href":189,"aria-hidden":79},"#awaiting-observables",[81,191,192],{"xmlns":83,"xmlns:xlink":84,"viewBox":85,"version":86,"width":87,"height":87,"aria-hidden":79},[89,193],{"fill":91,"fill-rule":92,"d":93},"Awaiting Observables",[64,196,197],{},"Having showed my colleague the above example and feeling very content, I suddenly realised that Reactive Extensions (Rx) can make the code even simpler. With the advent of the latest version of Reactive Extensions (Rx) you can now await observables and we can turn the method above into this:",[106,199],{"className":108,"language":109,"meta":110,"style":110,"html":200},"\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">public\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> async\u003C\u002Fspan>\u003Cspan class=\"sw29p\"> Task\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&lt;\u003C\u002Fspan>\u003Cspan class=\"sJvqV\">bool\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">?&gt; \u003C\u002Fspan>\u003Cspan class=\"sWm5y\">ShowDialog\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">()\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">{\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s4J9F\">    var\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> window\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> new\u003C\u002Fspan>\u003Cspan class=\"sw29p\"> MyDialogWindow\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s4J9F\">    var\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> closed\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> Observable\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">        .\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">FromEventPattern\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&lt;\u003C\u002Fspan>\u003Cspan class=\"sw29p\">EventHandler\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">, \u003C\u002Fspan>\u003Cspan class=\"sw29p\">EventArgs\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">&gt;(\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">            h\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =&gt;\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">Closed\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> +=\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> h\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">,\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">            h\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =&gt;\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">Closed\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> -=\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> h\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">);\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">    window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">Show\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">    await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> closed\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">FirstAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">()\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sFrd5\">    return\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> window\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">DialogResult\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">;\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sjLUg\">}\n\u003C\u002Fspan>\u003C\u002Fspan>",[64,202,132,203,206,207,210,211,214],{},[68,204,205],{},"await"," keyword is just some syntactic sugar in the C# language that makes writing thorny asynchronous code effortless. The real meat of what drives it is the ",[68,208,209],{},"GetAwaiter"," method. The Reactive Extensions (Rx) team seeing the genius that is the Task Parallel Library (TPL) took advantage. They added this method (actually an extension method) to ",[68,212,213],{},"IObservable\u003CT>",", allowing us to await an observable as seen in the example above.",[64,216,217],{},"However, there is a caveat which I shall explain. In the example above the Closed event could conceivably be fired any number of times (If the window was opened and closed a few times) and the observable wrapper around the Closed event never completes. So our observable returns multiple results but a task can only return a single result.",[64,219,220,221,224,225,227,228,232,233,236],{},"The secret in our example is the ",[68,222,223],{},"FirstAsync"," method. We are actually awaiting the first result returned by our observable and don't care about any further results. By default awaiting an observable without the ",[68,226,223],{}," method above will actually await the last result ",[229,230,231],"strong",{},"before completion",". If your observable does not complete, then you will be waiting ",[229,234,235],{},"forever","!",[64,238,239,240,242,243,246],{},"Handily the Reactive Extensions (Rx) team has added several methods which you can use before you use ",[68,241,205],{}," to modify the result of what you are awaiting. All of these methods end with the word ",[68,244,245],{},"Async",". I've added a short list of these methods below (There are lots of overloads so I've just highlighted the main ones):",[106,248],{"className":108,"language":109,"meta":110,"style":110,"html":249},"\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the first element of an observable sequence.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">FirstAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the first element of an observable sequence, or a default value if no such element exists.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">FirstOrDefaultAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the last element of an observable sequence. \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F This is the default action of awaiting an observable.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">LastAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the last element of an observable sequence, \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F or a default value if no such element exists.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">LastOrDefaultAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the only element of an observable sequence, and throws an exception if there is not exactly \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F one element in the observable sequence.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">SingleAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Returns the only element of an observable sequence, or a default value if the observable sequence \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F is empty; this method reports an exception if there is more than one element in the observable sequence.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">string\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> result\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =\u003C\u002Fspan>\u003Cspan class=\"sJvqV\"> await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">SingleOrDefaultAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">();\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan>\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F Invokes an action for each element in the observable sequence and returns a Task that will get \n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"s1q82\">\u002F\u002F signalled when the sequence terminates.\n\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan class=\"sJvqV\">await\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> observable\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">ForEachAsync\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">(\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">x\u003C\u002Fspan>\u003Cspan class=\"snCLD\"> =&gt;\u003C\u002Fspan>\u003Cspan class=\"sFrd5\"> Console\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">.\u003C\u002Fspan>\u003Cspan class=\"sWm5y\">WriteLine\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">(\u003C\u002Fspan>\u003Cspan class=\"sFrd5\">x\u003C\u002Fspan>\u003Cspan class=\"sjLUg\">));\n\u003C\u002Fspan>\u003C\u002Fspan>",[64,251,252,253,256],{},"All of the above methods allow you to pick a single result from your observable. ",[68,254,255],{},"ForEachAsync"," is different though as it performs an action on each item and when your observable completes (If it does) then the task completes.",[73,258,260,267],{"id":259},"conclusions",[17,261,263],{"href":262,"aria-hidden":79},"#conclusions",[81,264,265],{"xmlns":83,"xmlns:xlink":84,"viewBox":85,"version":86,"width":87,"height":87,"aria-hidden":79},[89,266],{"fill":91,"fill-rule":92,"d":93},"Conclusions",[64,269,270,271,273],{},"So we've learned how to await observables in different ways and how it can be another way of doing the same thing that ",[68,272,70],{}," does but in a cleaner more elegant way.",[64,275,276],{},"We've also learned that there are some caveats that you need to be aware of when awaiting an observable i.e. that observables return multiple results and you have to pick one to return in your task.",[278,279,280],"style",{},"html pre.shiki code .sJvqV, html code.shiki .sJvqV{--shiki-default:#0000FF;--shiki-dark:#F92672}html pre.shiki code .sw29p, html code.shiki .sw29p{--shiki-default:#267F99;--shiki-default-text-decoration:inherit;--shiki-dark:#A6E22E;--shiki-dark-text-decoration:underline}html pre.shiki code .sjLUg, html code.shiki .sjLUg{--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .sWm5y, html code.shiki .sWm5y{--shiki-default:#795E26;--shiki-dark:#A6E22E}html pre.shiki code .sFrd5, html code.shiki .sFrd5{--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .snCLD, html code.shiki .snCLD{--shiki-default:#000000;--shiki-dark:#F92672}html pre.shiki code .sMc8R, html code.shiki .sMc8R{--shiki-default:#0000FF;--shiki-dark:#AE81FF}html pre.shiki code .smL5M, html code.shiki .smL5M{--shiki-default:#AF00DB;--shiki-dark:#F92672}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4J9F, html code.shiki .s4J9F{--shiki-default:#0000FF;--shiki-default-font-style:inherit;--shiki-dark:#66D9EF;--shiki-dark-font-style:italic}html pre.shiki code .s1q82, html code.shiki .s1q82{--shiki-default:#008000;--shiki-dark:#88846F}",{"title":110,"searchDepth":282,"depth":282,"links":283},2,[],{"issue":285,"comments":289},{"number":286,"title":287,"html_url":288},107,"[Comment] Reactive Extensions (Rx) - Part 5 - Awaiting Observables","https:\u002F\u002Fgithub.com\u002FRehanSaeed\u002Frehansaeed.github.io\u002Fissues\u002F107",[290,302],{"id":291,"html_url":292,"body_html":293,"created_at":294,"user":295,"reactions":299},627272789,"https:\u002F\u002Fgithub.com\u002FRehanSaeed\u002Frehansaeed.github.io\u002Fissues\u002F107#issuecomment-627272789","\n\u003Cp>\u003Ca target=\"_blank\" rel=\"nofollow noopener noreferrer\" href=\"https:\u002F\u002Fcamo.githubusercontent.com\u002Fe32cce8adda5f86d4ece2d8a0322260ab87e14a6f8f737f157b53d4034d5f662\u002F68747470733a2f2f7777772e67726176617461722e636f6d2f6176617461722f31333131396535633030383166393464353464346663633562323530313761663f733d393626643d6d6d26723d67\">\u003Cimg alt=\"David Christensen\" height=\"40\" width=\"40\" src=\"https:\u002F\u002Fcamo.githubusercontent.com\u002Fe32cce8adda5f86d4ece2d8a0322260ab87e14a6f8f737f157b53d4034d5f662\u002F68747470733a2f2f7777772e67726176617461722e636f6d2f6176617461722f31333131396535633030383166393464353464346663633562323530313761663f733d393626643d6d6d26723d67\" \u002F>\u003C\u002Fa> \u003Cstrong>David Christensen\u003C\u002Fstrong> commented on \u003Cstrong>2017-01-11 12:04:21\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>In your observable ShowWindow example, I believe there is a (potential) race condition. Shouldn't your code be as shown below? Obviously for this particular example there is unlikely to be a problem, if you are demonstrating a pattern it might be worth correcting it?\u003C\u002Fp>\n\u003Cdiv>\u003Cpre>\u003Cspan>public\u003C\u002Fspan> \u003Cspan>async\u003C\u002Fspan> \u003Cspan>Task\u003C\u002Fspan> \u003Cspan>ShowDialog\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\n\u003Cspan>{\u003C\u002Fspan>\n    \u003Cspan>Window\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan> \u003Cspan>=\u003C\u002Fspan> \u003Cspan>new\u003C\u002Fspan> \u003Cspan>MyDialogWindow\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n    \u003Cspan>var\u003C\u002Fspan> \u003Cspan>closing\u003C\u002Fspan>\u003Cspan>=\u003C\u002Fspan> \u003Cspan>Observable\u003C\u002Fspan>\n        \u003Cspan>.\u003C\u002Fspan>\u003Cspan>FromEventPattern\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\n            h \u003Cspan>=&gt;\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Closed\u003C\u002Fspan> \u003Cspan>+=\u003C\u002Fspan> \u003Cspan>h\u003C\u002Fspan>\u003Cspan>,\u003C\u002Fspan>\n            h \u003Cspan>=&gt;\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Closed\u003C\u002Fspan> \u003Cspan>-=\u003C\u002Fspan> \u003Cspan>h\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n\n    \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Show\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n    \u003Cspan>await\u003C\u002Fspan> \u003Cspan>closing\u003C\u002Fspan>\n        \u003Cspan>.\u003C\u002Fspan>\u003Cspan>FirstAsync\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n \n    \u003Cspan>return\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>DialogResult\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n\u003Cspan>}\u003C\u002Fspan>\u003C\u002Fpre>\u003C\u002Fdiv>","2020-05-12T11:06:05Z",{"login":296,"avatar_url":297,"html_url":298},"RehanSaeed","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F2270364?v=4","https:\u002F\u002Fgithub.com\u002FRehanSaeed",{"url":300,"total_count":301,"+1":301,"-1":301,"laugh":301,"hooray":301,"confused":301,"heart":301,"rocket":301,"eyes":301},"https:\u002F\u002Fapi.github.com\u002Frepos\u002FRehanSaeed\u002Frehansaeed.github.io\u002Fissues\u002Fcomments\u002F627272789\u002Freactions",0,{"id":303,"html_url":304,"body_html":305,"created_at":306,"user":307,"reactions":308},627272831,"https:\u002F\u002Fgithub.com\u002FRehanSaeed\u002Frehansaeed.github.io\u002Fissues\u002F107#issuecomment-627272831","\n\u003Cp>\u003Ca target=\"_blank\" rel=\"nofollow noopener noreferrer\" href=\"https:\u002F\u002Fcamo.githubusercontent.com\u002F8a07049df41b8a3839a3f4342f09ea8e6e7fa0065667687f04beca2d088a1dca\u002F68747470733a2f2f7777772e67726176617461722e636f6d2f6176617461722f32623266393030653361633066353535316462646537323864336262343935343f733d393626643d6d6d26723d67\">\u003Cimg alt=\"Muhammad Rehan Saeed\" height=\"40\" width=\"40\" src=\"https:\u002F\u002Fcamo.githubusercontent.com\u002F8a07049df41b8a3839a3f4342f09ea8e6e7fa0065667687f04beca2d088a1dca\u002F68747470733a2f2f7777772e67726176617461722e636f6d2f6176617461722f32623266393030653361633066353535316462646537323864336262343935343f733d393626643d6d6d26723d67\" \u002F>\u003C\u002Fa> \u003Cstrong>\u003Ca rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\u002F\u002Frehansaeed.com\u002F\">Muhammad Rehan Saeed\u003C\u002Fa>\u003C\u002Fstrong> commented on \u003Cstrong>2017-01-11 14:25:38\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>In your observable ShowWindow example, I believe there is a (potential) race condition. Shouldn't your code be as shown below? Obviously for this particular example there is unlikely to be a problem, if you are demonstrating a pattern it might be worth correcting it?\u003C\u002Fp>\n\u003Cdiv>\u003Cpre>\u003Cspan>public\u003C\u002Fspan> \u003Cspan>async\u003C\u002Fspan> \u003Cspan>Task\u003C\u002Fspan> \u003Cspan>ShowDialog\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\n\u003Cspan>{\u003C\u002Fspan>\n    \u003Cspan>Window\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan> \u003Cspan>=\u003C\u002Fspan> \u003Cspan>new\u003C\u002Fspan> \u003Cspan>MyDialogWindow\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n    \u003Cspan>var\u003C\u002Fspan> \u003Cspan>closing\u003C\u002Fspan>\u003Cspan>=\u003C\u002Fspan> \u003Cspan>Observable\u003C\u002Fspan>\n        \u003Cspan>.\u003C\u002Fspan>\u003Cspan>FromEventPattern\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\n            h \u003Cspan>=&gt;\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Closed\u003C\u002Fspan> \u003Cspan>+=\u003C\u002Fspan> \u003Cspan>h\u003C\u002Fspan>\u003Cspan>,\u003C\u002Fspan>\n            h \u003Cspan>=&gt;\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Closed\u003C\u002Fspan> \u003Cspan>-=\u003C\u002Fspan> \u003Cspan>h\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n\n    \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>Show\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n    \u003Cspan>await\u003C\u002Fspan> \u003Cspan>closing\u003C\u002Fspan>\n        \u003Cspan>.\u003C\u002Fspan>\u003Cspan>FirstAsync\u003C\u002Fspan>\u003Cspan>(\u003C\u002Fspan>\u003Cspan>)\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n \n    \u003Cspan>return\u003C\u002Fspan> \u003Cspan>window\u003C\u002Fspan>\u003Cspan>.\u003C\u002Fspan>\u003Cspan>DialogResult\u003C\u002Fspan>\u003Cspan>;\u003C\u002Fspan>\n\u003Cspan>}\u003C\u002Fspan>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003C\u002Fblockquote>\n\u003Cp>Corrected, thanks!\u003C\u002Fp>","2020-05-12T11:06:12Z",{"login":296,"avatar_url":297,"html_url":298},{"url":309,"total_count":301,"+1":301,"-1":301,"laugh":301,"hooray":301,"confused":301,"heart":301,"rocket":301,"eyes":301},"https:\u002F\u002Fapi.github.com\u002Frepos\u002FRehanSaeed\u002Frehansaeed.github.io\u002Fissues\u002Fcomments\u002F627272831\u002Freactions","2014-03-27T00:00:00+00:00",null,"How and where to use Task Parallel Library (TPL) async and await with Reactive Extensions (Rx). Also, how to use TPL for awaiting observables.","md",[315,317,318],{"depth":316,"value":70},1,{"depth":316,"value":194},{"depth":316,"value":267},"\u002Fimages\u002Fhero\u002FReactive-Extensions-1366x768.png",{},true,"posts\u002F2014\u002Freactive-extensions-part5-awaiting-observables\u002Findex",[324,325,326,327,70,328],".NET","async await","Rx","Task Parallel Library","TPL",4,1792790624613]