{"id":487709,"date":"2024-07-02T14:19:49","date_gmt":"2024-07-02T13:19:49","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=dotnet&#038;p=487709"},"modified":"2024-07-02T15:55:14","modified_gmt":"2024-07-02T14:55:14","slug":"how-to-use-the-tasks-view-in-jetbrains-rider","status":"publish","type":"dotnet","link":"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2024\/07\/02\/how-to-use-the-tasks-view-in-jetbrains-rider","title":{"rendered":"How to use the Tasks View in JetBrains Rider"},"content":{"rendered":"\n<p>The Task Parallel Library (TPL) is foundational to all .NET applications, as it allows frameworks to write and execute multithreaded and parallel code. Additionally, developers looking to get the most out of their resources may want to write custom code, taking advantage of the types found in <code>System.Threading<\/code> and <code>System.Threading.Tasks<\/code>. You must understand concurrency and threading fundamentals to write fast and scalable solutions, including locks, deadlocks, awaits, and scheduling. Part of expanding your understanding of these concepts requires excellent tooling to help you visualize and make sense of a potentially chaotic swarm of executing tasks.<\/p>\n\n\n\n<p>Exciting news! We&#8217;ve recently launched the first iteration of our Tasks view, a powerful tool designed to help you understand the existing tasks in the current application process. <\/p>\n\n\n\n<p>In this post, we&#8217;ll examine the new tool window, discuss its essential UI elements, and demonstrate some common scenarios. You&#8217;ll be ready to explore your code bases and uncover optimization opportunities by the end.<\/p>\n\n\n    <div class=\"buttons\">\n        <div class=\"buttons__row\">\n                                                <a href=\"https:\/\/jetbrains.com\/rider\/next\/\" class=\"btn\" target=\"\" rel=\"noopener\">Download &amp; try JetBrains Rider<\/a>\n                                                    <\/div>\n    <\/div>\n\n\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Task Execution in .NET Applications<\/h2>\n\n\n\n<p>In .NET, Tasks offer an abstraction over concepts like concurrency and multithreading. The idea is to worry less about CPU cores and threads and deal with the high-level concepts of scheduling and executing work concurrently. This is generally great since it can help developers write more imperative code while efficiently utilizing all their system resources.<\/p>\n\n\n\n<p>While abstractions are reasonably good, no abstraction is perfect, and at some point, you&#8217;ll have to deal with the pitfalls of multiple tasks concurrently. These include deadlocks, race conditions, and inefficient scheduling that causes backpressure. Dealing with abstractions doesn&#8217;t mean you should not understand how and why they work.<\/p>\n\n\n\n<p>Typically, you will be responsible for scheduling tasks but never know when and how those tasks will be completed. Execution is the job of the .NET runtime. While you might see particular code patterns that are a sign of trouble to come, the best way to diagnose issues with Tasks is at runtime. Let&#8217;s look at some common scenarios you might uncover in your codebase and see how the Tasks view can help you better understand your applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Tasks<\/h2>\n\n\n\n<p>The most likely scenario when working with tasks is consuming an API that returns tasks that require the <code>async<\/code> and <code>await<\/code> keywords. These asynchronous APIs are in ASP.NET Core, MAUI, and Entity Framework Core. Many open-source projects have also moved to async-first APIs to support developer needs.<\/p>\n\n\n\n<p>Let&#8217;s take a look at a simple example.<\/p>\n\n\n                        <div class=\"rider-code-highlight rider-code-highlight__dark\">\n                <pre><code><span class=\"keyword\">await<\/span> <span class=\"method-name\">BasicWork<\/span>();\r\n\r\n<span class=\"keyword\">async<\/span> <span class=\"class-name\">Task<\/span> <span class=\"method-name\">BasicWork<\/span>()\r\n{\r\n    <span class=\"keyword\">await<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Delay<\/span>(<span class=\"struct-name\">TimeSpan<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">FromSeconds<\/span>(<span class=\"number\">1<\/span>));\r\n    <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"? Hello Tasks View!\"<\/span>);\r\n}\r\n<\/code><\/pre>\n                <div class=\"rider-code-highlight-btn-copy\"><div class=\"rider-code-highlight-tooltip\">Copy to clipboard<\/div><\/div>\n            <\/div>\n            \n\n\n\n\n\n\n<p>In this example, we have two tasks: The main task originating from our program and the <code>BasicWork<\/code> method. We can confirm this by using the new Tasks View. While in a debugging session, click the <b>Tasks<\/b> tab to view the following table.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2228\" height=\"337\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-09-23.png\" alt=\"\" class=\"wp-image-489458\"\/><figcaption class=\"wp-element-caption\">JetBrains Rider\u2019s Tasks View in Table mode<\/figcaption><\/figure><\/div>\n\n\n<p>You can also switch to a <b>Graph<\/b> view by choosing the option at the top right.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2220\" height=\"860\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-09-49.png\" alt=\"\" class=\"wp-image-489480\"\/><figcaption class=\"wp-element-caption\">JetBrains Rider\u2019s Tasks View in Graph mode<\/figcaption><\/figure><\/div>\n\n\n<p>You can also see the row information in the graph view by hovering over any stack item.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1038\" height=\"446\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-10-53.png\" alt=\"\" class=\"wp-image-489492\"\/><figcaption class=\"wp-element-caption\">Showing the row in the graph view<\/figcaption><\/figure><\/div>\n\n\n<p>When working with Tasks, there are <b>five statuses<\/b> any task can have at any one time:<\/p>\n\n\n\n<ul>\n<li><b>Active<\/b>: Currently executing and running.<\/li>\n\n\n\n<li><b>Scheduled<\/b>: The task has been created but has not yet been executed.<\/li>\n\n\n\n<li><b>Awaiting<\/b>: The task has been awaited but may be awaiting other tasks.<\/li>\n\n\n\n<li><b>Blocked<\/b>: This task is at the top of the stack, and the thread executing it is blocked (sleep, waiting on lock, etc.). There are also some other tasks higher in the stack.<\/li>\n\n\n\n<li><b>Deadlocked<\/b>: The task is in contention for a resource, and there&#8217;s a severe problem.<\/li>\n<\/ul>\n\n\n\n<p>Now that we&#8217;ve seen the most common scenario, let&#8217;s look at parented tasks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parented Tasks<\/h2>\n\n\n\n<p>The act of parenting allows developers to logically group tasks. When creating a task within a task, you can use the <code>TaskCreationOptions.AttachedToParent<\/code> to tie any new task to the containing task.<\/p>\n\n\n                        <div class=\"rider-code-highlight rider-code-highlight__dark\">\n                <pre><code><span class=\"keyword\">await<\/span> <span class=\"method-name\">ParentedTasks<\/span>();\r\n\r\n<span class=\"class-name\">Task<\/span> <span class=\"method-name\">ParentedTasks<\/span>()\r\n{\r\n    <span class=\"comment\">\/\/ Parent task<\/span>\r\n    <span class=\"keyword\">var<\/span> <span class=\"local-name\">parentTask<\/span> <span class=\"operator\">=<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"property-name static-symbol\">Factory<\/span><span class=\"operator\">.<\/span><span class=\"method-name\">StartNew<\/span>(() <span class=\"operator\">=&gt;<\/span>\r\n    {\r\n        <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">WriteLine<\/span>(<span class=\"string\">\"Parent task started.\"<\/span>);\r\n\r\n        <span class=\"comment\">\/\/ Child task<\/span>\r\n        <span class=\"keyword\">var<\/span> <span class=\"local-name\">task<\/span> <span class=\"operator\">=<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"property-name static-symbol\">Factory<\/span><span class=\"operator\">.<\/span><span class=\"method-name\">StartNew<\/span>(() <span class=\"operator\">=&gt;<\/span>\r\n        {\r\n            <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Child task started.\"<\/span>);\r\n            <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">Delay<\/span>(<span class=\"number\">2000<\/span>)<span class=\"operator\">.<\/span><span class=\"method-name\">Wait<\/span>(); <span class=\"comment\">\/\/ Simulating some work<\/span>\r\n            <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Child task completed.\"<\/span>);\r\n        }, <span class=\"enum-name\">TaskCreationOptions<\/span><span class=\"operator\">.<\/span><span class=\"enum-member-name\">AttachedToParent<\/span>);\r\n\r\n        <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Parent task doing some work.\"<\/span>);\r\n    }, <span class=\"enum-name\">TaskCreationOptions<\/span><span class=\"operator\">.<\/span><span class=\"enum-member-name\">AttachedToParent<\/span>);\r\n\r\n    <span class=\"comment\">\/\/ Wait for parent task to complete, which includes the children<\/span>\r\n    <span class=\"local-name\">parentTask<\/span><span class=\"operator\">.<\/span><span class=\"method-name\">Wait<\/span>();\r\n\r\n    <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Parent task completed.\"<\/span>);\r\n    <span class=\"keyword-control\">return<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"property-name static-symbol\">CompletedTask<\/span>;\r\n}\r\n<\/code><\/pre>\n                <div class=\"rider-code-highlight-btn-copy\"><div class=\"rider-code-highlight-tooltip\">Copy to clipboard<\/div><\/div>\n            <\/div>\n            \n\n\n\n\n\n\n<p>If you run the code and look at the Task view, you&#8217;ll see that we&#8217;ve successfully parented the child task.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2222\" height=\"400\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-25-41.png\" alt=\"\" class=\"wp-image-489503\"\/><figcaption class=\"wp-element-caption\">Showing a task parented to another<\/figcaption><\/figure><\/div>\n\n\n<p>Note that each new task has an integer <code>Id<\/code> assigned by the .NET runtime. These identifiers help you keep track of tasks that exist in your current process.<\/p>\n\n\n\n<p>This time, the graph view shows two async logical stacks resulting from the <code>ParentedTasks<\/code> code, which uses methods like <code>Wait<\/code> and returning <code>Task.CompletedTask<\/code>. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1322\" height=\"512\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-28-21.png\" alt=\"\" class=\"wp-image-489514\"\/><figcaption class=\"wp-element-caption\">Showing two async logical stacks<\/figcaption><\/figure><\/div>\n\n\n<p>That&#8217;s cool. Understanding whether tasks are related or have created separate logical stacks can help you understand if you&#8217;ve created a potential race condition.<\/p>\n\n\n\n<p>Let&#8217;s see how the Tasks view can help us see how work is scheduled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scheduling Tasks<\/h2>\n\n\n\n<p>Any time you <code>await<\/code> a task, you effectively schedule that work for a future time. That work can happen immediately after scheduling a task or after other scheduled tasks have been executed. Let&#8217;s see an example where we schedule several tasks and wait for them to complete.<\/p>\n\n\n                        <div class=\"rider-code-highlight rider-code-highlight__dark\">\n                <pre><code><span class=\"keyword\">await<\/span> <span class=\"method-name\">ScheduledWork<\/span>();\r\n<span class=\"keyword\">async<\/span> <span class=\"class-name\">Task<\/span> <span class=\"method-name\">ScheduledWork<\/span>()\r\n{\r\n    <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">Write<\/span>(<span class=\"string\">\"Let's work...\"<\/span>);\r\n    <span class=\"keyword\">var<\/span> <span class=\"local-name\">tasks<\/span> <span class=\"operator\">=<\/span> <span class=\"class-name static-symbol\">Enumerable<\/span>\r\n        <span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">Range<\/span>(<span class=\"number\">1<\/span>, <span class=\"number\">10<\/span>)\r\n        <span class=\"operator\">.<\/span><span class=\"extension-method-name\">Select<\/span>((<span class=\"parameter-name\">i<\/span>) <span class=\"operator\">=&gt;<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Run<\/span>(() <span class=\"operator\">=&gt;<\/span> <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Write<\/span>(<span class=\"parameter-name\">i<\/span>)));\r\n\r\n    <span class=\"keyword\">await<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WhenAll<\/span>(<span class=\"local-name\">tasks<\/span>);\r\n}\r\n<\/code><\/pre>\n                <div class=\"rider-code-highlight-btn-copy\"><div class=\"rider-code-highlight-tooltip\">Copy to clipboard<\/div><\/div>\n            <\/div>\n            \n\n\n\n\n\n\n<p>The use of the <code>Task.WhenAll<\/code> attempts to execute all the supplied tasks, with all of them being scheduled for future execution. You can see this in the Tasks view.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2218\" height=\"848\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-44-01.png\" alt=\"\" class=\"wp-image-489525\"\/><figcaption class=\"wp-element-caption\">Scheduled tasks from the 10 created tasks<\/figcaption><\/figure><\/div>\n\n\n<p>Additionally, the use of <code>Task.WhenAll<\/code> creates an async logical stack under which all these operations can run.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1684\" height=\"344\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-46-40.png\" alt=\"\" class=\"wp-image-489539\"\/><figcaption class=\"wp-element-caption\">Two async logical stacks with one showing 10 values<\/figcaption><\/figure><\/div>\n\n\n<p>When you step through the code during the debugging session, you&#8217;ll see the list of Tasks reduced as tasks are completed. You may also notice multiple tasks being executed at the same time.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2223\" height=\"1438\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-10-47-51.png\" alt=\"\" class=\"wp-image-489561\"\/><figcaption class=\"wp-element-caption\">A dwindling set of tasks in the tasks view<\/figcaption><\/figure><\/div>\n\n\n<p>It&#8217;s satisfying to see tasks completed, but it&#8217;s not great when they overstay their welcome. Let&#8217;s move on to the scariest scenario when dealing with tasks: deadlocks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deadlocks<\/h2>\n\n\n\n<p>The most common cause of a deadlock is contention around a shared resource guarded by some locking mechanism. Locks are essential when dealing with shared resources but can lead to app-breaking issues.<\/p>\n\n\n\n<p>Let&#8217;s create a deadlock now because we love to live dangerously. More importantly, we&#8217;ll see how the Tasks view can help us identify it. We&#8217;ll schedule two tasks, each trying to lock the same variables.<\/p>\n\n\n                        <div class=\"rider-code-highlight rider-code-highlight__dark\">\n                <pre><code><span class=\"keyword\">await<\/span> <span class=\"method-name\">Deadlock<\/span>();\r\n\r\n<span class=\"comment\">\/\/ This method will cause a deadlock<\/span>\r\n<span class=\"comment\">\/\/ proceed with caution, oOOoOOoOo! ?<\/span>\r\n<span class=\"keyword\">async<\/span> <span class=\"class-name\">Task<\/span> <span class=\"method-name\">Deadlock<\/span>()\r\n{\r\n    <span class=\"keyword\">object<\/span> <span class=\"local-name\">one<\/span> <span class=\"operator\">=<\/span> <span class=\"keyword\">new<\/span>();\r\n    <span class=\"keyword\">object<\/span> <span class=\"local-name\">two<\/span> <span class=\"operator\">=<\/span> <span class=\"keyword\">new<\/span>();\r\n\r\n    <span class=\"keyword\">var<\/span> <span class=\"local-name\">timer<\/span> <span class=\"operator\">=<\/span> <span class=\"keyword\">new<\/span> <span class=\"namespace-name\">System<\/span><span class=\"operator\">.<\/span><span class=\"namespace-name\">Timers<\/span><span class=\"operator\">.<\/span><span class=\"class-name\">Timer<\/span>(\r\n        <span class=\"struct-name\">TimeSpan<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">FromSeconds<\/span>(<span class=\"number\">2<\/span>)\r\n    ) { <span class=\"property-name\">Enabled<\/span> <span class=\"operator\">=<\/span> <span class=\"keyword\">true<\/span>, <span class=\"property-name\">AutoReset<\/span> <span class=\"operator\">=<\/span> <span class=\"keyword\">false<\/span> };\r\n\r\n    <span class=\"local-name\">timer<\/span><span class=\"operator\">.<\/span><span class=\"event-name\">Elapsed<\/span> <span class=\"operator\">+=<\/span> (<span class=\"keyword\">_<\/span>, <span class=\"keyword\">_<\/span>) <span class=\"operator\">=&gt;<\/span>\r\n    {\r\n        <span class=\"comment\">\/\/ only see this if we're deadlocked<\/span>\r\n        <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"?Deadlock\"<\/span>);\r\n    };\r\n\r\n    <span class=\"keyword\">await<\/span> <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WhenAll<\/span>(<span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Run<\/span>(() <span class=\"operator\">=&gt;<\/span>\r\n    {\r\n        <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">WriteLine<\/span>(<span class=\"string\">\"Getting lock for one.\"<\/span>);\r\n        <span class=\"keyword\">lock<\/span> (<span class=\"local-name\">one<\/span>)\r\n        {\r\n            <span class=\"class-name\">Thread<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">Sleep<\/span>(<span class=\"number\">1000<\/span>);\r\n            <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"static-symbol method-name\">WriteLine<\/span>(<span class=\"string\">\"Getting lock two in first task.\"<\/span>);\r\n            <span class=\"keyword\">lock<\/span> (<span class=\"local-name\">two<\/span>)\r\n            {\r\n            }\r\n        }\r\n    }), <span class=\"class-name\">Task<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Run<\/span>(() <span class=\"operator\">=&gt;<\/span>\r\n    {\r\n        <span class=\"static-symbol class-name\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Getting lock two in second task.\"<\/span>);\r\n        <span class=\"keyword\">lock<\/span> (<span class=\"local-name\">two<\/span>)\r\n        {\r\n            <span class=\"class-name\">Thread<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">Sleep<\/span>(<span class=\"number\">1000<\/span>);\r\n            <span class=\"class-name static-symbol\">Console<\/span><span class=\"operator\">.<\/span><span class=\"method-name static-symbol\">WriteLine<\/span>(<span class=\"string\">\"Getting lock one in second task.\"<\/span>);\r\n            <span class=\"keyword\">lock<\/span> (<span class=\"local-name\">one<\/span>)\r\n            {\r\n            }\r\n        }\r\n    }));\r\n}\r\n<\/code><\/pre>\n                <div class=\"rider-code-highlight-btn-copy\"><div class=\"rider-code-highlight-tooltip\">Copy to clipboard<\/div><\/div>\n            <\/div>\n            \n\n\n\n\n\n\n<p>When you run the code, you&#8217;ll notice the application never exits. In the <b>Run<\/b> toolbar, hit the pause button to pause the application. Oh no, a deadlock! I&#8217;m shocked! (well, I&#8217;m not that shocked).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2040\" height=\"466\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-11-06-43.png\" alt=\"\" class=\"wp-image-489572\"\/><figcaption class=\"wp-element-caption\">A deadlocked pair of tasks in the tasks table view<\/figcaption><\/figure><\/div>\n\n\n<p>The graph view is even more telling, showing the two tasks in contention and how we got here.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1276\" height=\"530\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-11-07-39.png\" alt=\"\" class=\"wp-image-489583\"\/><figcaption class=\"wp-element-caption\">A deadlocked pair of tasks in the tasks graph view<\/figcaption><\/figure><\/div>\n\n\n<p>Double-clicking on any of the deadlocked logical stacks will take you to the location of the deadlock.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2144\" height=\"1890\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/07\/JetBrains-Rider-EAP-2024-06-26-11-10-42.png\" alt=\"\" class=\"wp-image-489594\"\/><figcaption class=\"wp-element-caption\">Showing the code that is causing the deadlock in JetBrains Rider<\/figcaption><\/figure><\/div>\n\n\n<p>That ease of navigation should make finding and solving deadlocks, well, dead simple.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>The Tasks view is currently available in <a href=\"https:\/\/jetbrains.com\/rider\/next\/\" target=\"_blank\" rel=\"noopener\">JetBrains Rider 2024.2 EAP<\/a>, and we&#8217;d love to hear your feedback so you can help shape this tool&#8217;s future. We understand that tasks can be a challenging part of .NET development, and we hope this additional tooling can help you overcome them. Try it and see if it can help you optimize existing code or find longstanding issues in your codebase.<\/p>\n\n\n\n<p>Thanks for reading, and we look forward to your thoughts and comments.<\/p>\n\n\n    <div class=\"buttons\">\n        <div class=\"buttons__row\">\n                                                <a href=\"https:\/\/jetbrains.com\/rider\/next\/\" class=\"btn\" target=\"\" rel=\"noopener\">Download the latest version!<\/a>\n                                                    <\/div>\n    <\/div>\n\n\n\n\n\n\n\n<p><sub><em>image credit: <a href=\"https:\/\/unsplash.com\/@edenconstantin0\" target=\"_blank\" rel=\"noopener\">Eden Constantino<\/a><\/em><\/sub><\/p>\n","protected":false},"author":1079,"featured_media":487918,"comment_status":"closed","ping_status":"closed","template":"","categories":[4992],"tags":[2026,211,1978,1110],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/487709"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/dotnet"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/1079"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=487709"}],"version-history":[{"count":11,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/487709\/revisions"}],"predecessor-version":[{"id":499055,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/487709\/revisions\/499055"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/487918"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=487709"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=487709"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=487709"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=487709"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}