-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1412 from microsoft/docfx
Migrate docs to docfx-based GitHub Pages
- Loading branch information
Showing
83 changed files
with
1,544 additions
and
1,466 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1 @@ | ||
# VSTHRD001 Avoid legacy thread switching methods | ||
|
||
Switching to the UI thread should be done using `JoinableTaskFactory.SwitchToMainThreadAsync` | ||
rather than legacy methods such as `Dispatcher.Invoke` or `ThreadHelper.Invoke`. | ||
This avoids deadlocks and can reduce threadpool starvation. | ||
|
||
## Examples of patterns that are flagged by this analyzer | ||
|
||
```csharp | ||
ThreadHelper.Generic.Invoke(delegate { | ||
DoSomething(); | ||
}); | ||
``` | ||
|
||
or | ||
|
||
```cs | ||
Dispatcher.CurrentDispatcher.BeginInvoke(delegate { | ||
DoSomething(); | ||
}); | ||
``` | ||
|
||
## Solution | ||
|
||
Use `await SwitchToMainThreadAsync()` instead, wrapping with the `JoinableTaskFactory`'s `Run` or `RunAsync` method if necessary: | ||
|
||
```csharp | ||
void Foo() { | ||
ThreadHelper.JoinableTaskFactory.Run(async delegate { | ||
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); | ||
DoSomething(); | ||
}); | ||
} | ||
``` | ||
|
||
In the above example, we obtain a `JoinableTaskFactory` instance from the `ThreadHelper.JoinableTaskFactory` static property | ||
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. | ||
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. | ||
|
||
### Replacing Dispatcher.BeginInvoke | ||
|
||
When updating calls to `Dispatcher.BeginInvoke`, there are a few considerations to consider. | ||
|
||
1. `BeginInvoke` schedules the delegate for execution later. | ||
1. `BeginInvoke` always executes the delegate on the dispatcher's thread. | ||
1. `BeginInvoke` schedules the delegate at some given priority, or default priority determined by the dispatcher. | ||
|
||
To resolve a warning for such code, it is often sufficient to replace it with this, which is *roughly* equivalent: | ||
|
||
```cs | ||
await joinableTaskFactory.RunAsync(async delegate { | ||
await joinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true); | ||
DoSomething(); | ||
}) | ||
``` | ||
|
||
The first line in the delegate is necessary to match the behaviors of 1 and 2 on the above list. | ||
When the caller is known to already be on the main thread, you can simplify it slightly to this: | ||
|
||
```cs | ||
await joinableTaskFactory.RunAsync(async delegate { | ||
await Task.Yield(); | ||
DoSomething(); | ||
}) | ||
``` | ||
|
||
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. | ||
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. | ||
|
||
Altogether, this might look like: | ||
|
||
```cs | ||
await joinableTaskFactory.WithPriority(DispatcherPriority.DataBind).RunAsync(async delegate { | ||
await joinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true); | ||
DoSomething(); | ||
}) | ||
``` | ||
|
||
## Configuration | ||
|
||
This analyzer is configurable via the `vs-threading.LegacyThreadSwitchingMembers.txt` file. | ||
See our [configuration](configuration.md) topic for more information. | ||
This content has been moved to [GitHub Pages](https://microsoft.github.io/vs-threading/analyzers/VSTHRD001.html). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1 @@ | ||
# VSTHRD002 Avoid problematic synchronous waits | ||
|
||
Synchronously waiting on `Task`, `ValueTask`, or awaiters is dangerous and may cause dead locks. | ||
|
||
## Examples of patterns that are flagged by this analyzer | ||
|
||
```csharp | ||
void DoSomething() | ||
{ | ||
DoSomethingElseAsync().Wait(); | ||
DoSomethingElseAsync().GetAwaiter().GetResult(); | ||
var result = CalculateSomethingAsync().Result; | ||
} | ||
``` | ||
|
||
## Solution | ||
|
||
Please consider the following options: | ||
|
||
1. Switch to asynchronous wait if the caller is already a "async" method. | ||
1. Change the chain of callers to be "async" methods, and then change this code to be asynchronous await. | ||
1. Use `JoinableTaskFactory.Run()` to wait on the tasks or awaiters. | ||
|
||
```csharp | ||
async Task DoSomethingAsync() | ||
{ | ||
await DoSomethingElseAsync(); | ||
await DoSomethingElseAsync(); | ||
var result = await CalculateSomethingAsync(); | ||
} | ||
|
||
void DoSomething() | ||
{ | ||
joinableTaskFactory.Run(async delegate | ||
{ | ||
await DoSomethingElseAsync(); | ||
await DoSomethingElseAsync(); | ||
var result = await CalculateSomethingAsync(); | ||
}); | ||
} | ||
``` | ||
|
||
Refer to [Asynchronous and multithreaded programming within VS using the JoinableTaskFactory][1] for more information. | ||
|
||
[1]: https://devblogs.microsoft.com/premier-developer/asynchronous-and-multithreaded-programming-within-vs-using-the-joinabletaskfactory/ | ||
This content has been moved to [GitHub Pages](https://microsoft.github.io/vs-threading/analyzers/VSTHRD002.html). |
Oops, something went wrong.