{"id":8025,"date":"2017-04-10T08:39:05","date_gmt":"2017-04-10T16:39:05","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/?p=8025"},"modified":"2024-07-05T12:36:37","modified_gmt":"2024-07-05T19:36:37","slug":"easy-async-and-await-for-vbs-part-1-or","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/easy-async-and-await-for-vbs-part-1-or\/","title":{"rendered":"Easy Async and Await for VBs Part 1, or&#8230;"},"content":{"rendered":"<h3>&#8230;letting your code do absolutely nothing!<\/h3>\n<p>We\u2019ve all been there, one way or the other. Either as users of an app or as the developer to whom users complained to: When a typical Win32 app is waiting for an operation to complete, we often get to see something like this:<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/03\/00HangingNativeWindow.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/04\/00HangingNativeWindow.png\" alt=\"00hangingnativewindow\" width=\"551\" height=\"232\" class=\"alignnone size-full wp-image-8035\" \/><\/a><\/p>\n<p>In discussions about how to get a handle on such scenarios there are all kinds of suggestions, one of the most frequent ones being \u201cYou need to do this asynchronously: Just start a new thread! You can do that with Tasks.\u201d And this is when people start introducing patterns like the following into their code which in most cases is not only unnecessary but is dangerously wrong!<\/p>\n<p>So, let\u2019s go back to the original problem for a second and figure out the root cause for that. Principally your app hangs like this when the so-called <i>Message Loop<\/i> of your app gets blocked. Every app (well, web apps excluded) has some kind of message loop, no matter if your app is a Windows Forms app, or if you based your app on WPF, UWP or even Xamarin on Android or iOS \u2013 for the latter, they are called <i>Run Loops<\/i> or <i>Looper<\/i>, but they are basically the same.<\/p>\n<p>For a profound understanding of Async and Await it is helpful to know what happens behind the scenes, when and why a message loop gets blocked. After all, one of the primary domains of Async and Await is to address lacking responsiveness of apps. To achieve this, we need to keep the message loop clear as often as possible. So, let\u2019s take a closer look at a rather unusual VB demo app, whose solution is called <i>BlockingMessageLoop.<\/i> You can find this demo in a GitHub Repo that you can clone or download <a href=\"https:\/\/github.com\/microsoft\/\">from here<\/a>. This demo displays a simple window with a button on the screen. You can click the button, which causes a loop to spin just to use up processor workload \u2013 which means it gets blocked, and you will end up with a result like that in the previous screenshot. So far so simple. This demo, however, is not your typical Windows Forms app. It implements everything without the WinForms base classes, so you can see \u2013 although very simplified \u2013 what <i>actually<\/i> happens behind the scenes, when you work with Forms, Controls and Events:<\/p>\n<p>As you can see here, there are no classes for the parts of what usually would be the task of a Form. The demo only consists of a Module, starting with <i>Sub Main<\/i>, and that method first creates the main window by calling <i>CreateWindow<\/i> and <i>CreateButton<\/i>, which puts a Button in that Window. This is the way how Windows development already was done in pure C a couple of decades ago, and of course, you could or can \u2013 if you wanted \u2013 still do this the \u201coriginal way\u201d also in VB. What\u2019s more important here is what <i>Sub Main<\/i> also does: It is starting the app\u2019s<i> Message Loop<\/i>, which looks like this:<\/p>\n<p>All Windows apps follow this same scheme. They create the windows, place control inside those windows (principally, controls are a special form of windows themselves), and then they start the message loop at some point, which runs as long as the main window is visible on the screen. Whenever something happens with the windows or the controls, Windows sends a message to the app informing it about the nature of the event: When the app needs to redraw the content of a window for example, this message is WM_PAINT; when the user clicks a Command Button, the message is WM_COMMAND \u2013 just to point out a few.<\/p>\n<p>For the app to actually be getting those messages, it calls a Windows function named <i>GetMessage<\/i>. <i>GetMessage<\/i> waits until the next message for that app arrives, and while waiting it does not use up any processor workload \u2013 the app just idles. When the app then got the next message, it needs to run two additional functions: The first \u2013 <i>TranslateMessage<\/i> \u2013 is to process additional keyboard commands, and the second \u2013 <i>DispatchMessage<\/i> \u2013 is to send the message to a special message processing handler, usually called <i>WndProc<\/i> (Windows Procedure):<\/p>\n<p>By the way: The <i>DispatchMessage<\/i> function of Windows knows this <i>WndProc<\/i> method, because this method has been passed as a delegate when the main window of the app had originally been created.<\/p>\n<p>So, now assume, the user of your app clicks the button, and the app should do something which really needs a long time to complete. For example, calculating 100,000 digits of Pi. Or writing a big file on a memory stick. What happens if you put that code into WndProc? Well, <i>WndProc<\/i> does not return to <i>DispatchMessage<\/i> for a long time, either. Which means, the message loop cannot continue, which means no additional messages are coming through \u2013 your app becomes not responding. This is exactly what happens, if you were to put code for an excessive workload in a button\u2019s click event handler in a Windows Forms or WPF app. And when that happens, it always causes Window to apply an emergency plan on your app: If your app does not react to any Windows messages within two seconds, Windows creates a new window which has the same title as that of the hanging app plus the famous words we all so love: \u201cnot responding\u201d. Windows copies the last known content into this new window \u2013 only in a somewhat \u201cblurry\u201d version. Windows then hides the hanging app\u2019s window from the screen and finally pretends, the new window is yours app\u2019s main window for the time being. Now the user can at least move the hanging app\u2019s window out of the way \u2013 or at least so it seems. Truth is, it is not at all the app\u2019s window, but some fake copy.<\/p>\n<h2>Save us, DoEvents!<\/h2>\n<p>As Visual Basic developers of several years, in such scenarios we know what to do, do we not? Only the few really know, what it actually does internally, but we\u2019ve all used it at some point: We just invoke <i>DoEvents<\/i> in our lengthy methods, and all of the sudden apps do no longer hang, as if by magic! Well, here\u2019s the magic:<\/p>\n<p>Some magic, right? All <i>DoEvents<\/i> does is to peek if there are any new messages. And if so, well, it simply does the same that the message loop does: It translates and dispatches the message, which causes the app no longer to hang, when we have a long-running worker method like in <i>WndProc, <\/i>because queued messages get processed by<i> WndProc <\/i>(and successively also by <i>DefWindowsProc<\/i>, which takes care of things like moving or resizing the window). But be careful: Since we allowed for messages to be processed within the still running worker method, the user can click on the button again, which causes <i>WndProc<\/i> to be called recursively another time. The chain: User clicks button, message loop calls <i>DispatchMessage<\/i>, <i>DispatchMessage<\/i> calls <i>WndProc<\/i>, <i>WndProc<\/i> runs worker code, worker code calls <i>DoEvents<\/i>, User has clicked the button again, <i>DoEvents<\/i> calls <i>GetMessage<\/i> and <i>DispatchMessage<\/i>, <i>DispatchMessage<\/i> calls <i>WndProc<\/i> again and so the worker code gets started<i> <\/i>a second time &#8211; of course not in parallel, just recursively. So, you want to make sure to disable your controls, when the worker code starts, and only enable the controls again, when the worker code completes. The takeaway of this scenario: Keep the Message Loop clear if you want the most responsive app!<\/p>\n<h2>Wasting time by doing nothing<\/h2>\n<p>Now let\u2019s look at the next demo in the GitHub repo, which is called <i>SyncVsAsync<\/i>. This demo is to show what happens if you have an app with a method which uses up a lot of processor workload, and you want to process something else in addition, like putting a big file on a storage device. Let\u2019s say, on a memory stick:<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/03\/01WorkLoadDemo.gif\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/04\/01WorkLoadDemo.gif\" alt=\"01workloaddemo\" width=\"756\" height=\"680\" class=\"alignnone size-full wp-image-8045\" \/><\/a><\/p>\n<p>When you start the app, it immediately begins with its heavy workload routine: It calculates 100,000 digits of Pi. Since it uses <i>DoEvents<\/i> while calculating, you\u2019re still be able to control the app: All Windows messages get processed, so you can not only move the window around, you can also pick a folder on a memory stick, which you should have plugged in your computer beforehand. (This demo principally also works with the internal hard drive; unfortunately, those disks are so fast these days that everything happens too quickly to spot \u2013 since a thumb drive is considerable slower, a thumb drive does the trick, here).<\/p>\n<p>If you\u2019ve picked the folder, try this while the app is doing its calculations: Open the Task Manager by right-clicking the task bar. Sort the list by name. You should see the demo app in the list and, depending on how many cores your processor has, that it is using a pretty good amount of processor workload. Place the task manager, so you can see it and the app at the same time, click the button <i>Write File Sync\u2026<\/i>, and observe what happens:<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/03\/02SaveToMemStick.gif\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/04\/02SaveToMemStick.gif\" alt=\"02savetomemstick\" width=\"756\" height=\"680\" class=\"alignnone size-full wp-image-8046\" \/><\/a><\/p>\n<p>As soon as you click the button, the app starts to write the binary file of about 100 Mbyte on the memory stick. This causes two things: Incoming Windows messages are obviously no longer getting processed. The last update you see in the dialog is \u201cSaving File\u2026\u201d, but after that everything stops. No display refresh. You can no longer move the window. But what you also notice: Your app does no longer use up ANY processor workload \u2013 it seems to do absolutely nothing, yet \u2013 check it out when it\u2019s done \u2013 the file still gets written on the memory stick! So, what\u2019s happening here? What is writing the actual file?<\/p>\n<p>The truth is: Not the processor. Simplified put, by calling <i>fs.Write<\/i> in the code above, the processor tells some IO chip in your tablet or PC \u201cHere, have the file at that memory address and with that length, and put it on the stick for me. Call me, when you\u2019re done!\u201d. Well, and then the processor sits there, suspends itself and waits to be reactivated, if you will. But what it also does <i>not<\/i> do: Running the message loop. Or calling at least DoEvents occasionally. The result: Your app hangs, until <i>fs.Write<\/i> internally received that call back, and the method can continue and eventually return. <\/p>\n<h2>Asynchronous Operations to the Best-Practice-Rescue!<\/h2>\n<p>Now let\u2019s revisit the <i>Task.Run<\/i> code from the beginning. Do you notice now how senseless this code is? That sample code is explicitly spinning off another task, and the only thing this task does is to wait for an I\/O-Operation to complete. <i>Task.Run<\/i> means: We are utilizing an additional thread, and with that we probably using up additional resources like another processor core. And by doing that, we\u2019re confusing two concepts: I\/O bound workload and CPU bound workload. The latter we apply, when we do some expensive work inside our code, like calculating 100.000 digits of pi. The first one, however, we need when we&#8217;re putting a file on a storage device. Or pulling data from the network. Both of which can be run asynchronously. Understanding the difference of those two is essential here!<\/p>\n<p>Even without using Async and Await, .NET was always able to handle asynchronous scenarios. And that still works. But it gets, well, kind of messy when writing the code for that. Let\u2019s find out what happens, when we restart the demo app, and this time click on the second button <i>Write file Async<\/i>\u2026 . Here\u2019s the code for that:<\/p>\n<p>Notice, that we use a slightly different version of the write method here: <i>BeginWrite<\/i> is initiating an asynchronous operation. We\u2019re just telling the OS, it should offload the actual writing-to-device-operation to that component inside the computer, which is responsible for putting the file on the memory stick. Along, we\u2019re passing the call-back method <i>EndWriteFileProc<\/i>. <strong><\/p>\n<p>Important:<\/strong> When you create a file stream, make sure you prepare that file stream for asynchronous operations. It is important to know that it does not suffice to just use the asynchronous versions of the file operation functions (<i>Begin<\/i>Write, <i>Begin<\/i>Read, etc.). The OS needs to be prepared for asynchrony as well, if you will. You do this by setting the flags parameters you\u2019re passing to the <i>FileStream<\/i> constructor manually, determine a buffer big enough to hold the full size of what you are going to write (or read), and pass a flag indicating that you want everything asynchronous underneath. If your code forgets this, the opposite of what you want to achieve will happen: Despite using asynchronous versions of the file operations, the actual IO work is done synchronously \u2013 wrapped in thread by the framework, it just <i>feels<\/i> to be asynchronous. But it is not.<\/p>\n<p>When the operation completes, the OS should call that method, so we\u2019d be notified and could do the cleanup:<\/p>\n<p>Again, we can spot a problem, here: For each asynchronous operation, an app needs to kick off, it must put code in two different methods. Imagine, how a big code base would have looked like some 10 years ago, had an app already used asynchronous calls intensely. The result: pure spaghetti code!<\/p>\n<h2>A method with a spot which does absolutely nothing (thus letting the Message Loop loop)!<\/h2>\n<p>Now, there is (an even weirder) way to do this in just one method. When we adjust the kick off method to have the same signature as the callback, and we implement a simple state machine to differentiate if the method acts currently as the kick off or the callback part, we could unify both methods, thus having a much cleaner program flow:<\/p>\n<p>And yes, I know. In the code above, I use the evil <i>GoTo<\/i>, and yes, I could have done that with <i>If<\/i> as well. But the separation of purposes would not have been so obvious, and that&#8217;s the most important point of this example!<\/p>\n<p>In any case, we achieved the goal: The code is readably placed in one method, it is awaiting the callback, and while doing that, it does not claim the program control: Between the two parts, the message loop can run, and the app does not hang at any point while the file is written to its destination device.<\/p>\n<h2>And at last: Async and Await<\/h2>\n<p>Starting with Visual Studio 2012, Visual Basic and C# both introduced the <i>Await<\/i> operator to simplify such scenarios significantly. But coming up with new keywords for a programming language is not an easy task, because you\u2019re always running the risk of breaking existing code. Imagine a method like this one:<\/p>\n<p>What\u2019s going to happen with that if <i>Await<\/i> as a new keyword became available per se? The code would break. This is where <i>Async<\/i> comes into play. It does not do much, when applied to a method. It is just decorating a method and telling the compiler: &#8220;You will very likely find one or more <i>Await<\/i> operators in this method, so, please build the required state machines already for awaiting the asynchronous calls which return tasks.&#8221; Which results in important takeaway #1: No <i>Async<\/i> keyword on the method\u2019s signature, no <i>Await<\/i> allowed in the method\u2019s body. It&#8217;s as simple as that. Just decorating a method with <i>Async<\/i> does not do anything to the method. (Well, only internally, but it does not change the nature of the method at all.)<\/p>\n<p>Important takeaway #2: The <i>Await<\/i> operator awaits <i>Tasks<\/i>. (Well, to be completely accurate, Await awaits everything that exposes the so called <i>awaitable pattern<\/i>, and Tasks are one of them you will be dealing with quite often). Tasks are promises that a certain method will be executed at some point. Does that mean a new task always runs parallel to the current task (where all the UI related stuff happens)? Not at all! It might at some point. But it absolutely does not have to run in parallel. Asynchronous just means \u201cwill be happening\u201d or \u201ca result will be available at some point\u201d.<\/p>\n<p>There is a rule that a certain method in the .NET Framework (or in any other library, although there is no guarantee for this) is returning such a promise through <i>Task<\/i>, namely if the method\u2019s name ends with \u201cAsync\u201d. Thus, it\u2019s comparatively easy to figure out the methods for that: In our Write-To-Memory-Stick sample we are using the <i>Write<\/i> and the <i>Flush<\/i> methods. If we resort to IntelliSense for our <i>FileStream<\/i> variable <i>fs<\/i>, we quickly discover the methods <i>WriteAsync<\/i> and <i>FlushAsync<\/i> \u2013 both doing the same as their synchronous counterparts, but returning <i>Task<\/i>, thus being able to be awaited.<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/03\/03IntelliSenseAsync.gif\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/vbteam\/wp-content\/uploads\/sites\/7\/2017\/04\/03IntelliSenseAsync.gif\" alt=\"03intellisenseasync\" width=\"669\" height=\"320\" class=\"alignnone size-full wp-image-8055\" \/><\/a><\/p>\n<p>Oh, and one more and very important thing: If you do not have a really good and exceptional reason, and you absolutely know what you are doing, you should <strong>never<\/strong> call Async methods which do <strong>not<\/strong> return <i>Task<\/i> or <i>Task(Of SomeType)<\/i>. Or, for us VBs in other words: only call Async <i>Functions<\/i> yourself, avoid calling Async <i>Subs<\/i> directly. You may ask yourself now, when you are not supposed to call Async Subs, why would you implement them to begin with, when they get never called? Well, there are some type of Subs which <i>you<\/i> never call, but which get called in your apps: Event Handlers! Those <i>can<\/i> be under normal circumstances considered to be save if they are Async Subs, because your code does not usually call them directly, but rather they get called. The reason for that is simple: Tasks are promises, so they include a callback mechanism when the actual task is done. This is pretty much what we learned when we used <i>BeginWrite<\/i> and <i>EndWrite<\/i> in a previous sample. The callback method <i>EndFileProc<\/i> was the promise, if you will, in that sample, just done the old-fashioned way. A <i>Task<\/i> now can encapsulate both the initiating call and the callback in one entity. And awaiting a task enqueues the processing of that promise and picks up the control flow when the promise is delivered. In the meantime: the message loop runs while the actual method just sits there and does nothing. (Again, almost in same way as we did it in the sample of the state machine \u2013 take another look!) What\u2019s important to know: A method returning a <i>Task<\/i> (a Function of type <i>Task<\/i>) <i>can<\/i> deliver that promise back to the caller. A Sub never returns anything to the caller. The methods inside an Async Sub gets executed all right, but there is no <i>Task<\/i> (promise) which can be returned \u2013 it is a one-way street, and that\u2019s the reason why it is also called \u201cfire and forget\u201d (and why it also should <i>always<\/i> have an exception handler, because crashing inside an Async Sub can crash the whole app. In some scenarios, even without any exception message dialog or crash report \u2013 your app would just be gone.) Let\u2019s put this together now:<\/p>\n<p>As we just pointed out: Async Subs are OK, when they have Event Handler characteristics. Our <i>Click<\/i> event handler can therefore be an Async Sub. What is curious though on first glance is the next method <i>WriteFileCommandProcAsync<\/i>: Although it is a Function, it does not return Task, and the compiler on top does not complain that the method is not returning any result. But that\u2019s OK! Since we decorated this method with Async and we\u2019re returning Task, the method\u2019s body holds the code for <i>the promise<\/i>. So, inside an Async Function we are returning the result of that promise not that promise itself. Which means:<\/p>\n<p>That means on the caller side:<\/p>\n<p>And now it\u2019s up to you: Go, experiment! Refactor your apps to be more responsive, and discover the goodness of Async and Await!<\/p>\n<p>Happy VB coding, leave your comments, stay tuned for the next part, and Tsch\u00fcss from Germany!<\/p>\n<p>Klaus L\u00f6ffelmann<\/p>\n<p>(Follow me on twitter @loeffelmann)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8230;letting your code do absolutely nothing! We\u2019ve all been there, one way or the other. Either as users of an app or as the developer to whom users complained to: When a typical Win32 app is waiting for an operation to complete, we often get to see something like this: In discussions about how to [&hellip;]<\/p>\n","protected":false},"author":9483,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,6,14,195],"tags":[36,39,91,102,129,148],"class_list":["post-8025","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-how-to","category-tips-and-tricks","category-visual-basic","tag-async","tag-await","tag-klaus-loeffelmann","tag-message-loop","tag-promises","tag-task"],"acf":[],"blog_post_summary":"<p>&#8230;letting your code do absolutely nothing! We\u2019ve all been there, one way or the other. Either as users of an app or as the developer to whom users complained to: When a typical Win32 app is waiting for an operation to complete, we often get to see something like this: In discussions about how to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/8025","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/9483"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=8025"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/8025\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=8025"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=8025"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=8025"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}