{"id":81628,"date":"2023-02-09T08:00:23","date_gmt":"2023-02-09T07:00:23","guid":{"rendered":"https:\/\/code-maze.com\/?p=81628"},"modified":"2023-02-09T08:33:57","modified_gmt":"2023-02-09T07:33:57","slug":"asynchronous-programming-patterns-dotnet","status":"publish","type":"post","link":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/","title":{"rendered":"Asynchronous Programming Patterns in .NET"},"content":{"rendered":"<p>In this article, we are going to learn about the various patterns to implement asynchronous programming in .NET.<\/p>\n<p>.NET has had in-built support for asynchronous programming since the release of .NET Framework 1.1. It has been through various improvements over the years, and today it&#8217;s a powerful mainstream programming paradigm.<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To download the source code for this article, you can visit our <a href=\"https:\/\/github.com\/CodeMazeBlog\/CodeMazeGuides\/tree\/main\/async-csharp\/AsynchronousProgrammingPatterns\" target=\"_blank\" rel=\"nofollow noopener\">GitHub repository<\/a>.<\/div>\n<p>Let&#8217;s start by understanding what asynchronous programming is.<\/p>\n<h2>Asynchronous Programming<\/h2>\n<p>Asynchronous programming enables multiple operations to run concurrently without waiting for any other operations to complete. Besides, it has a non-blocking nature where the program continues to execute other tasks while executing long-running operations.<\/p>\n<p>Check out our article on <a href=\"https:\/\/code-maze.com\/asynchronous-programming-with-async-and-await-in-asp-net-core\/\" target=\"_blank\" rel=\"noopener\">Asynchronous Programming Using TAP<\/a> to know more.<\/p>\n<p>Currently, <strong>TAP is the recommended pattern for implementing asynchronous programming in .NET<\/strong>. Although APM and EAP are now legacy models, it&#8217;s important to understand them when dealing with legacy projects or libraries.<\/p>\n<p>There are 3 patterns for implementing asynchronous programming in .NET:<\/p>\n<ul>\n<li>Asynchronous Programming Model (APM)<\/li>\n<li>Event-Based Asynchronous Pattern (EAP)<\/li>\n<li>Task-Based Asynchronous Pattern (TAP)<\/li>\n<\/ul>\n<p>So, let&#8217;s now dive into each of these.<\/p>\n<h2>Asynchronous Programming Model (APM)<\/h2>\n<p>.NET Framework 1.1 introduced asynchronous programming with APM. <strong>This model uses the <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.iasyncresult?view=net-7.0\" target=\"_blank\" rel=\"nofollow noopener\"><code>IAsyncResult<\/code><\/a> design pattern to perform asynchronous programming.<\/strong><\/p>\n<p><code>IAsyncResult<\/code> interface is the return type of a method that initiates an asynchronous operation while a method that concludes an asynchronous operation receives this as a parameter.<\/p>\n<p>For example, to implement an asynchronous operation named <code>OperationName<\/code> using <code>IAsyncResult<\/code> pattern, we use two methods named <code>BeginOperationName()<\/code> and <code>EndOperationName()<\/code>. <strong>These methods denote the beginning and end of the asynchronous operation.<\/strong><\/p>\n<p>The <code>BeginOperationName()<\/code> method starts the asynchronous operation and returns an output type that implements the <code>IAsyncResult<\/code> interface. In addition to operation parameters, it can accept a callback method that fires on operation completion. We can also pass an operation context state where we normally pass any dependencies.<\/p>\n<h3>Asynchronous Programming Implementation<\/h3>\n<p>The main building blocks for creating an APM implementation are:<\/p>\n<ul>\n<li>Two methods to start and end asynchronous operations<\/li>\n<li>A <code>delegate<\/code> of <code>AsyncCallback<\/code> type that fires on operation completion<\/li>\n<li>Optional <code>state<\/code> property that holds dependencies<\/li>\n<\/ul>\n<p>A typical example of the APM model is the <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.io.filestream?view=net-7.0\" target=\"_blank\" rel=\"nofollow noopener\"><code>FileStream<\/code><\/a> class in <code>System.IO<\/code> namespace. It defines <code>BeginRead()<\/code> and <code>EndRead()<\/code> methods to asynchronously read bytes from a file. Let&#8217;s see how to use them:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class ApmFileReader\r\n{\r\n    private byte[]? _buffer;\r\n    private const int InputReportLength = 1024;\r\n    private FileStream? _fileStream;\r\n\r\n    public void BeginReadAsync()\r\n    {\r\n        _buffer = new byte[InputReportLength];\r\n        _fileStream = File.OpenRead(\"User.txt\");\r\n        _fileStream.BeginRead(_buffer, 0, InputReportLength, ReadCallbackAsync, _buffer);\r\n    }\r\n\r\n    public void ReadCallbackAsync(IAsyncResult iResult)\r\n    {\r\n        _fileStream?.EndRead(iResult);\r\n        var buffer = iResult.AsyncState as byte[];\r\n    }\r\n}<\/pre>\n<p>The <code>BeginRead()<\/code> method of the <code>FileStream<\/code> class accepts an optional state parameter and a callback of <code>AsyncCallback<\/code> delegate type:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">delegate void AsyncCallback(IAsyncResult ar);<\/code><\/p>\n<p>For this purpose, we define the <code>ReadCallbackAsync()<\/code> method. Within this method, we call the <code>EndRead()<\/code> method of <code>FileStream<\/code> class to wait for the pending asynchronous read operation to complete.\u00a0<\/p>\n<p>The callback method also receives a reference to an <code>IAsyncResult<\/code> object. Hence, it can query the <code>AsyncState<\/code> property of the <code>IAsyncResult<\/code> interface to obtain the reference of the state object.\u00a0<\/p>\n<p>Now, we define the <code>BeginReadAsync()<\/code> method to read the file asynchronously. We start the asynchronous operation by invoking the <code>BeginRead()<\/code> method of the <code>FileStream<\/code> class.\u00a0<\/p>\n<h2>Event-Based Asynchronous Pattern (EAP)<\/h2>\n<p>As the name implies, <strong>with EAP, we use events to implement asynchronous operations.<\/strong> The operations execute in separate threads, and we use events to notify the completion status.<\/p>\n<p>Check out our article on <a href=\"https:\/\/code-maze.com\/csharp-events\/\" target=\"_blank\" rel=\"noopener\">Events in C#<\/a> if you are new to this topic.<\/p>\n<p>Applications with UI components mainly use EAP for implementations. This model keeps the UI components responsive while running time-consuming operations as the components don&#8217;t need to wait for the operations to complete.<\/p>\n<p>A long-running operation executes in a separate thread making the UI thread free. The UI thread subscribes to the event that notifies the completion of the long-running operation by registering a callback method. Thus, the UI doesn&#8217;t need to wait till the operation is complete.<\/p>\n<p>EAP is not just limited to UI components, we can use it to implement various operations asynchronously. For instance, downloading a file, web service calls, etc.<\/p>\n<p>.NET Framework 2.0 introduced EAP. Similar to APM, even EAP is a legacy model as Microsoft recommends using TAP.<\/p>\n<h3>Asynchronous Programming Implementation<\/h3>\n<p>To implement an asynchronous operation with EAP, we first need an event, <code>OperationNameCompleted<\/code> that fires on operation completion.\u00a0<\/p>\n<p>Next, we need a custom event argument <code>OperationNameEventArgs<\/code> where we can define custom properties to store any operations results and event statuses.<\/p>\n<p>Finally, we create the asynchronous operation using <code>OperationNameAsync()<\/code> method and pass any required parameters to run the asynchronous operation.<\/p>\n<p>Let&#8217;s see this in practice by implementing an asynchronous operation that fetches user information.<\/p>\n<h3>EAP Code Example<\/h3>\n<p>First, let&#8217;s create a simple <code>User<\/code> class that holds user attributes:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class User\r\n{\r\n    public int Id { get; set; }\r\n\r\n    public string? Name { get; set; }\r\n}<\/pre>\n<p>Secondly, we create a <code>UserService<\/code> that emulates a long-running operation:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class UserService\r\n{\r\n    private readonly List&lt;User&gt; _users = new List&lt;User&gt;\r\n    {\r\n        new User { Id = 100, Name = \"Adam\"},\r\n        new User { Id = 101, Name = \"Eve\"}\r\n    };\r\n\r\n    public User GetUser(int userId)\r\n    {\r\n        \/\/ Long-running operation\r\n        return _users.FirstOrDefault(x =&gt; x.Id == userId);\r\n    }\r\n}<\/pre>\n<p>Now, we define the event argument:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class GetUserCompletedEventArgs : AsyncCompletedEventArgs\r\n{\r\n    private User _result;\r\n\r\n    public User Result\r\n    {\r\n        get\r\n        {\r\n            RaiseExceptionIfNecessary();\r\n            return _result;\r\n        }\r\n    }\r\n\r\n    public GetUserCompletedEventArgs(Exception error, bool cancelled, User user)\r\n        : base(error, cancelled, user)\r\n    {\r\n        _result = user;\r\n    }\r\n}<\/pre>\n<p>The event argument class derives from the <code>GetUserCompletedEventArgs<\/code> class and holds event-related information. We use this to identify the operation status and retrieve the results. In addition to that, we use the <code>RaiseExceptionIfNecessary()<\/code> method of <code>AsyncCompletedEventArgs<\/code> class to raise an exception if the operation failed or was canceled.<\/p>\n<p>After that, we create the <code>EapUserProvider<\/code> class with EAP implementation:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class EapUserProvider\r\n{\r\n    private readonly SendOrPostCallback _operationFinished;\r\n    private readonly UserService _userService;\r\n\r\n    public EapUserProvider()\r\n    {\r\n        _operationFinished = ProcessOperationFinished;\r\n        _userService = new UserService();\r\n    }\r\n\r\n    public User GetUser(int userId) =&gt; _userService.GetUser(userId);\r\n\r\n    public event EventHandler&lt;GetUserCompletedEventArgs&gt; GetUserCompleted;\r\n\r\n    public void GetUserAsync(int userId) =&gt; GetUserAsync(userId, null);\r\n\r\n    private void ProcessOperationFinished(object state)\r\n    {\r\n        var args = (GetUserCompletedEventArgs)state;\r\n\r\n        GetUserCompleted?.Invoke(this, args);\r\n    }\r\n}<\/pre>\n<p>The <code>_operationFinished<\/code> field is a <code>SendOrPostCallback<\/code> delegate that represents a callback method that we want to execute when a message dispatches to a synchronization context.<\/p>\n<p>We assign <code>ProcessOperationFinished()<\/code> the\u00a0 <code>_operationFinished<\/code> delegate. So, <code>ProcessOperationFinished()<\/code> fires once the task finishes and the call returns to the current synchronization context.<\/p>\n<p>The <code>GetUserCompleted<\/code> property represents the event that fires on operation completion. This provides the option for consumers to subscribe to this operation.<\/p>\n<p>Then, we add the <code>GetUserAsync()<\/code> method to the <code>EapUserProvider<\/code> class and fetch the user asynchronously:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public void GetUserAsync(int userId, object userState)\r\n{\r\n    AsyncOperation operation = AsyncOperationManager.CreateOperation(userState);\r\n\r\n    ThreadPool.QueueUserWorkItem(state =&gt;\r\n    {\r\n        GetUserCompletedEventArgs args;\r\n        try\r\n        {\r\n            var user = GetUser(userId);\r\n            args = new GetUserCompletedEventArgs(null, false, user);\r\n        }\r\n        catch (Exception e)\r\n        {\r\n            Console.WriteLine(e.Message);\r\n            args = new GetUserCompletedEventArgs(e, false, null);\r\n        }\r\n\r\n        operation.PostOperationCompleted(_operationFinished, args);\r\n\r\n    }, userState);\r\n}<\/pre>\n<p>The <code>GetUserAsync()<\/code> method encapsulates the EAP implementation logic.<\/p>\n<p>First, we create an <code>AsyncOperation<\/code> object to track and report the progress of the asynchronous task. Thereupon, we run the operation asynchronously on a thread pool using the <code>ThreadPool.QueueWorkItem()<\/code> method. Then we notify about the operation completion by invoking the <code>PostOperationCompleted()<\/code> method from the <code>AsyncOperation<\/code> object. This in turn fires the <code>GetUserCompleted<\/code> event.<\/p>\n<p>Next, let&#8217;s create a <code>EventBasedAsyncPatternHelper<\/code> class and add the <code>FetchAndPrintUser()<\/code> method to perform the asynchronous operation using EAP:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public static class EventBasedAsyncPatternHelper\r\n{\r\n    public static void FetchAndPrintUser(int userId)\r\n    {\r\n        var eapUserProvider = new EapUserProvider();\r\n\r\n        eapUserProvider.GetUserCompleted += (sender, args) =&gt;\r\n        {\r\n            var result = args.Result;\r\n            Console.WriteLine($\"Id: {result.Id}\\nName: {result.Name}\");\r\n        };\r\n\r\n        eapUserProvider.GetUserAsync(userId);\r\n    }\r\n}<\/pre>\n<p>We register for the <code>GetUserCompleted<\/code> event by defining our callback method that prints user information. Then, we start the asynchronous operation by invoking the <code>GetUserAsync()<\/code> method.<\/p>\n<p>Finally, let&#8217;s call the <code>FetchAndPrintUser()<\/code> method to retrieve and print the user information asynchronously:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">EventBasedAsyncPatternHelper.FetchAndPrintUser(100);<\/code><\/p>\n<h2>Task-Based Asynchronous Pattern (TAP)<\/h2>\n<p>TAP is the recommended pattern of implementing asynchronous operations in .NET for new development. This pattern emerged from the <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/standard\/parallel-programming\/task-parallel-library-tpl\" target=\"_blank\" rel=\"nofollow noopener\">Task Parallel Library<\/a> introduced in .NET Framework 4.0. <\/p>\n<p>TAP uses <code>async<\/code> and <code>await<\/code> keywords to implement the pattern. The compiler creates a state machine for methods with <code>async<\/code> keywords to handle the asynchronous execution.<\/p>\n<p>Meanwhile, the <code>await<\/code> keyword pauses the execution and asynchronously waits for the awaited <code>Task<\/code> to complete. At this point, the current thread releases to the thread pool as it unblocks and picks up another task.<\/p>\n<p>To know more about task-based async programming, check out our article on <a href=\"https:\/\/code-maze.com\/csharp-execute-multiple-tasks-asynchronously\/\" target=\"_blank\" rel=\"noopener\">executing multiple tasks asynchronously<\/a>.<\/p>\n<h3>Asynchronous Programming Implementation<\/h3>\n<p>We can implement TAP with or without the <code>async<\/code> keyword:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public Task&lt;int&gt; OperationName1Async(int param)\r\n{\r\n    \/\/ more code\r\n    return Task.FromResult(1);\r\n}\r\n\r\npublic async Task&lt;int&gt; OperationName2Async(int\u00a0param)\r\n{\r\n    \/\/ more code with await\r\n    return 1;\r\n}<\/pre>\n<p>With TAP, we define an asynchronous method that normally returns <code>Task<\/code> or <code>Task&lt;T&gt;<\/code>. In the first example, <code>OperationName1Async()<\/code> returns a <code>Task<\/code> object. This encapsulates the whole asynchronous lifecycle and it&#8217;s our responsibility to manage it manually to create, run and close the task.<\/p>\n<p>On the other hand, the <code>OperationName2Async()<\/code> method is using the <code>async<\/code> keyword. It&#8217;s the simplest version of implementing asynchronous patterns in .NET to date. The compiler generates methods to manage the <code>Task<\/code> lifecycle and we only need to manage it by using the <code>async<\/code> and <code>await<\/code> keywords.<\/p>\n<h3>CancellationToken<\/h3>\n<p>An important advantage of using tasks is the ability to cancel the task at any time. For example, suppose a user navigates from one web page to another, while a long-running operation is in progress. In that case, it makes sense to cancel the operation from the previous page if it is no longer needed.<\/p>\n<p>We can achieve this using the <code>CancellationToken<\/code> mechanism of <code>Task<\/code>. Basically, a <code>CancellationToken<\/code> is a carrier of cancellation requests. It&#8217;s an optional parameter that we can pass to asynchronous operations. The asynchronous operations monitor this token for any cancellation requests and abort accordingly.<\/p>\n<p>Here is a simple example that uses a cancellation token to abort the task:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var cancelToken = new CancellationTokenSource();\r\nTask.Factory.StartNew(async () =&gt;\r\n{\r\n    await Task.Delay(3000, cancelToken.Token);\r\n    \/\/ API call\r\n}, cancelToken.Token);\r\n\r\n\/\/Stops the task\r\ncancelToken.Cancel(false);<\/pre>\n<p>The <code>Cancel()<\/code> method of the <code>CancellationTokenSource<\/code> class notifies of a cancellation request and all the tasks that use the token will abort.<\/p>\n<p>Check out our article <a href=\"https:\/\/code-maze.com\/canceling-http-requests-in-asp-net-core-with-cancellationtoken\/\" target=\"_blank\" rel=\"noopener\">Canceling HTTP Requests in ASP.NET Core<\/a>, where we discuss more about <code>CancellationToken<\/code>.<\/p>\n<p>Let&#8217;s see TAP in action by implementing the same user fetch asynchronous operation we did for EAP. But this time, using TAP.<\/p>\n<h3>TAP Code Example<\/h3>\n<p>We start by defining a\u00a0<code>TapUserProvider<\/code> class with TAP implementation:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class TapUserProvider\r\n{\r\n    private readonly UserService _userService;\r\n\r\n    public TapUserProvider()\r\n    {\r\n        _userService = new UserService();\r\n    }\r\n\r\n    public User GetUser(int userId) =&gt; _userService.GetUser(userId);\r\n\r\n    public Task&lt;User&gt; GetUserAsync(int userId)\r\n    {\r\n        return Task.Run(() =&gt; GetUser(userId));\r\n    }\r\n}<\/pre>\n<p>The <code>GetUserAsync()<\/code> method spins up a thread using the <code>Task.Run()<\/code> method and calls the user service to fetch the user information.<\/p>\n<p>After that, we create a <code>TaskBasedAsyncPatternHelper<\/code> class with <code>FetchAndPrintUser()<\/code> method to asynchronously call the <code>GetUserAsync()<\/code> method using <code>async<\/code> and <code>await<\/code> keywords:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public static class TaskBasedAsyncPatternHelper\r\n{\r\n    public static async Task FetchAndPrintUser(int userId)\r\n    {\r\n        var tapUserProvider = new TapUserProvider();\r\n\r\n        var user = await tapUserProvider.GetUserAsync(userId);\r\n\r\n        Console.WriteLine($\"Id: {user.Id}\\nName: {user.Name}\");\r\n    }\r\n}<\/pre>\n<p>As the <code>GetUserAsync()<\/code> method returns a <code>Task<\/code>, we use <code>await<\/code> keyword to wait for the execution to finish. Post completion, the code after <code>await<\/code> keyword executes and prints the user information.<\/p>\n<p>Finally, let&#8217;s invoke the <code>FetchAndPrintUser()<\/code> method to retrieve and print user information:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">await TaskBasedAsyncPatternHelper.FetchAndPrintUser(100);<\/code><\/p>\n<h2>Conclusion<\/h2>\n<p>To sum it up, we have learned about asynchronous programming and how it has evolved in .NET from APM to TAP using practical examples.<\/p>\n<p><strong>TAP is the recommended approach in .NET to implement async programming, while Microsoft considers APM and EAP as legacy models<\/strong>. It is also easier to implement TAP since it only uses a single method to represent the initiation and completion of an asynchronous operation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we are going to learn about the various patterns to implement asynchronous programming in .NET. .NET has had in-built support for asynchronous programming since the release of .NET Framework 1.1. It has been through various improvements over the years, and today it&#8217;s a powerful mainstream programming paradigm. Let&#8217;s start by understanding what [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":62189,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[504],"tags":[10,1622,158,884,1621,482,1623,1624],"class_list":["post-81628","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-design-pattern","tag-net","tag-apm","tag-asynchronous","tag-asynchronous-programming","tag-asynchronous-programming-patterns","tag-design-pattern","tag-eap","tag-tap","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Asynchronous Programming Patterns in .NET<\/title>\n<meta name=\"description\" content=\"Asynchronous programming enables multiple operations to run concurrently. Let&#039;s learn a few different patterns in asynchronous programming.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchronous Programming Patterns in .NET\" \/>\n<meta property=\"og:description\" content=\"Asynchronous programming enables multiple operations to run concurrently. Let&#039;s learn a few different patterns in asynchronous programming.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2023-02-09T07:00:23+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-02-09T07:33:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Code Maze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Code Maze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\"},\"author\":{\"name\":\"Code Maze\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\"},\"headline\":\"Asynchronous Programming Patterns in .NET\",\"datePublished\":\"2023-02-09T07:00:23+00:00\",\"dateModified\":\"2023-02-09T07:33:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\"},\"wordCount\":1498,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png\",\"keywords\":[\".NET\",\"APM\",\"Asynchronous\",\"Asynchronous Programming\",\"Asynchronous Programming Patterns\",\"Design Pattern\",\"EAP\",\"TAP\"],\"articleSection\":[\"Design Pattern\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\",\"url\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\",\"name\":\"Asynchronous Programming Patterns in .NET\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png\",\"datePublished\":\"2023-02-09T07:00:23+00:00\",\"dateModified\":\"2023-02-09T07:33:57+00:00\",\"description\":\"Asynchronous programming enables multiple operations to run concurrently. Let's learn a few different patterns in asynchronous programming.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png\",\"width\":1100,\"height\":620,\"caption\":\"C# Development\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Asynchronous Programming Patterns in .NET\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04\",\"name\":\"Code Maze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png\",\"caption\":\"Code Maze\"},\"description\":\"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/codemaze\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/codemazecontributor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Asynchronous Programming Patterns in .NET","description":"Asynchronous programming enables multiple operations to run concurrently. Let's learn a few different patterns in asynchronous programming.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/","og_locale":"en_US","og_type":"article","og_title":"Asynchronous Programming Patterns in .NET","og_description":"Asynchronous programming enables multiple operations to run concurrently. Let's learn a few different patterns in asynchronous programming.","og_url":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/","og_site_name":"Code Maze","article_published_time":"2023-02-09T07:00:23+00:00","article_modified_time":"2023-02-09T07:33:57+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png","type":"image\/png"}],"author":"Code Maze","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Code Maze","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/"},"author":{"name":"Code Maze","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04"},"headline":"Asynchronous Programming Patterns in .NET","datePublished":"2023-02-09T07:00:23+00:00","dateModified":"2023-02-09T07:33:57+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/"},"wordCount":1498,"commentCount":0,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png","keywords":[".NET","APM","Asynchronous","Asynchronous Programming","Asynchronous Programming Patterns","Design Pattern","EAP","TAP"],"articleSection":["Design Pattern"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/","url":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/","name":"Asynchronous Programming Patterns in .NET","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png","datePublished":"2023-02-09T07:00:23+00:00","dateModified":"2023-02-09T07:33:57+00:00","description":"Asynchronous programming enables multiple operations to run concurrently. Let's learn a few different patterns in asynchronous programming.","breadcrumb":{"@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2021\/12\/social-csharp.png","width":1100,"height":620,"caption":"C# Development"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/asynchronous-programming-patterns-dotnet\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Asynchronous Programming Patterns in .NET"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/09d29b223012c8e94a68ba62861d0b04","name":"Code Maze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez-150x150.png","caption":"Code Maze"},"description":"This is the standard author on the site. Most articles are published by individual authors, with their profiles, but when several authors have contributed, we publish collectively as a part of this profile.","sameAs":["https:\/\/www.linkedin.com\/company\/codemaze\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/codemazecontributor\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/81628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=81628"}],"version-history":[{"count":5,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/81628\/revisions"}],"predecessor-version":[{"id":81633,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/81628\/revisions\/81633"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/62189"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=81628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=81628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=81628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}