|
1 |
| -# VSTHRD001 Avoid legacy thread switching methods |
2 |
| - |
3 |
| -Switching to the UI thread should be done using `JoinableTaskFactory.SwitchToMainThreadAsync` |
4 |
| -rather than legacy methods such as `Dispatcher.Invoke` or `ThreadHelper.Invoke`. |
5 |
| -This avoids deadlocks and can reduce threadpool starvation. |
6 |
| - |
7 |
| -## Examples of patterns that are flagged by this analyzer |
8 |
| - |
9 |
| -```csharp |
10 |
| -ThreadHelper.Generic.Invoke(delegate { |
11 |
| - DoSomething(); |
12 |
| -}); |
13 |
| -``` |
14 |
| - |
15 |
| -or |
16 |
| - |
17 |
| -```cs |
18 |
| -Dispatcher.CurrentDispatcher.BeginInvoke(delegate { |
19 |
| - DoSomething(); |
20 |
| -}); |
21 |
| -``` |
22 |
| - |
23 |
| -## Solution |
24 |
| - |
25 |
| -Use `await SwitchToMainThreadAsync()` instead, wrapping with the `JoinableTaskFactory`'s `Run` or `RunAsync` method if necessary: |
26 |
| - |
27 |
| -```csharp |
28 |
| -void Foo() { |
29 |
| - ThreadHelper.JoinableTaskFactory.Run(async delegate { |
30 |
| - await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); |
31 |
| - DoSomething(); |
32 |
| - }); |
33 |
| -} |
34 |
| -``` |
35 |
| - |
36 |
| -In the above example, we obtain a `JoinableTaskFactory` instance from the `ThreadHelper.JoinableTaskFactory` static property |
37 |
| -as it exists within Visual Studio itself. Other applications should create and expose their own `JoinableTaskContext` and/or `JoinableTaskFactory` for use in code that run in these applications. |
38 |
| -See our doc on [consuming `JoinableTaskFactory` from a library](https://github.com/microsoft/vs-threading/blob/main/doc/library_with_jtf.md) for more information. |
39 |
| - |
40 |
| -### Replacing Dispatcher.BeginInvoke |
41 |
| - |
42 |
| -When updating calls to `Dispatcher.BeginInvoke`, there are a few considerations to consider. |
43 |
| - |
44 |
| -1. `BeginInvoke` schedules the delegate for execution later. |
45 |
| -1. `BeginInvoke` always executes the delegate on the dispatcher's thread. |
46 |
| -1. `BeginInvoke` schedules the delegate at some given priority, or default priority determined by the dispatcher. |
47 |
| - |
48 |
| -To resolve a warning for such code, it is often sufficient to replace it with this, which is *roughly* equivalent: |
49 |
| - |
50 |
| -```cs |
51 |
| -await joinableTaskFactory.RunAsync(async delegate { |
52 |
| - await joinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true); |
53 |
| - DoSomething(); |
54 |
| -}) |
55 |
| -``` |
56 |
| - |
57 |
| -The first line in the delegate is necessary to match the behaviors of 1 and 2 on the above list. |
58 |
| -When the caller is known to already be on the main thread, you can simplify it slightly to this: |
59 |
| - |
60 |
| -```cs |
61 |
| -await joinableTaskFactory.RunAsync(async delegate { |
62 |
| - await Task.Yield(); |
63 |
| - DoSomething(); |
64 |
| -}) |
65 |
| -``` |
66 |
| - |
67 |
| -Matching behavior 3 on the list above may be important when the dispatcher priority is specified in the BeginInvoke call and was chosen for a particular reason. |
68 |
| -In such a case, you can ensure that `JoinableTaskFactory` matches that priority instead of using its default by creating a special `JoinableTaskFactory` instance with the priority setting you require using the [`JoinableTaskFactory.WithPriority`](https://learn.microsoft.com/dotnet/api/microsoft.visualstudio.threading.dispatcherextensions.withpriority?view=visualstudiosdk-2022) method. |
69 |
| - |
70 |
| -Altogether, this might look like: |
71 |
| - |
72 |
| -```cs |
73 |
| -await joinableTaskFactory.WithPriority(DispatcherPriority.DataBind).RunAsync(async delegate { |
74 |
| - await joinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true); |
75 |
| - DoSomething(); |
76 |
| -}) |
77 |
| -``` |
78 |
| - |
79 |
| -## Configuration |
80 |
| - |
81 |
| -This analyzer is configurable via the `vs-threading.LegacyThreadSwitchingMembers.txt` file. |
82 |
| -See our [configuration](configuration.md) topic for more information. |
| 1 | +This content has been moved to [GitHub Pages](https://microsoft.github.io/vs-threading/analyzers/VSTHRD001.html). |
0 commit comments