Skip to content

Commit

Permalink
Merge branch 'dev/andarno/libtemplateUpdate' into renovate/vstest-mon…
Browse files Browse the repository at this point in the history
…orepo
  • Loading branch information
AArnott committed Feb 10, 2025
2 parents d894468 + 79c76b3 commit a2f4717
Show file tree
Hide file tree
Showing 87 changed files with 1,554 additions and 1,472 deletions.
8 changes: 8 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@
"matchPackageNames": ["xunit.runner.visualstudio"],
"allowedVersions": "<3.0"
},
{
"matchPackageNames": ["xunit.combinatorial"],
"allowedVersions": "<2.0"
},
{
"matchDatasources": ["dotnet-version", "docker"],
"matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"],
"groupName": "Dockerfile and global.json updates"
},
{
"matchPackageNames": ["*"],
"allowedVersions": "!/-g[a-f0-9]+$/"
},
{
"matchPackageNames": [
"System.Collections.Immutable",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs_validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: 🔗 Markup Link Checker (mlc)
uses: becheran/mlc@v0.19.2
uses: becheran/mlc@v0.21.0
with:
args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/*,https://badges.gitter.im/*,https://github.com/*,https://app.gitter.im/* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://msrc.microsoft.com/*,https://www.microsoft.com/msrc*,https://microsoft.com/msrc*,https://microsoft.sharepoint.com/*
- name: ⚙ Install prerequisites
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<!-- Local builds should embed PDBs so we never lose them when a subsequent build occurs. -->
<DebugType Condition=" '$(CI)' != 'true' and '$(TF_BUILD)' != 'true' ">embedded</DebugType>

<PackageProjectUrl>https://github.com/Microsoft/vs-threading</PackageProjectUrl>
<PackageProjectUrl>https://microsoft.github.io/vs-threading/</PackageProjectUrl>
<Company>Microsoft</Company>
<Authors>Microsoft</Authors>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
Expand Down
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<MicroBuildVersion>2.0.181</MicroBuildVersion>
<MicroBuildVersion>2.0.187</MicroBuildVersion>
<CodeAnalysisVersion>3.11.0</CodeAnalysisVersion>
<CodeAnalysisVersionForTests>4.12.0</CodeAnalysisVersionForTests>
<CodefixTestingVersion>1.1.2</CodefixTestingVersion>
Expand Down Expand Up @@ -52,7 +52,7 @@
<ItemGroup Label="Library.Template">
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.VisualStudio.Internal.MicroBuild.NonShipping" Version="$(MicroBuildVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<PackageVersion Include="xunit" Version="2.9.3" />
</ItemGroup>
<ItemGroup>
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@

Async synchronization primitives, async collections, TPL and dataflow extensions. The JoinableTaskFactory allows synchronously blocking the UI thread for async work. This package is applicable to any .NET application (not just Visual Studio).

[Overview documentation](doc/index.md).
[Getting started](https://microsoft.github.io/vs-threading/docs/getting-started.html).

[See the full list of features](src/Microsoft.VisualStudio.Threading/README.md).
[See the full list of features](https://microsoft.github.io/vs-threading/docs/features.html).

## Microsoft.VisualStudio.Threading.Analyzers

[![NuGet package](https://img.shields.io/nuget/v/Microsoft.VisualStudio.Threading.Analyzers.svg)](https://www.nuget.org/packages/Microsoft.VisualStudio.Threading.Analyzers)

Static code analyzer to detect common mistakes or potential issues regarding threading and async coding.

[Diagnostic analyzer rules](doc/analyzers/index.md).

[See the full list of features](src/Microsoft.VisualStudio.Threading.Analyzers.CodeFixes/README.md).
[Diagnostic analyzer rules](https://microsoft.github.io/vs-threading/analyzers/index.html).
4 changes: 2 additions & 2 deletions azure-pipelines/install-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ steps:
- template: WIFtoPATauth.yml
parameters:
wifServiceConnectionName: azure-public/vside package pull
deadPATServiceConnectionId: 0ae39abc-4d06-4436-a7b5-865833df49db # azure-public/msft_consumption
deadPATServiceConnectionId: 46f0d4d4-9fff-4c58-a1ab-3b8f97e3b78a # azure-public/msft_consumption_public

- task: NuGetAuthenticate@1
displayName: 🔏 Authenticate NuGet feeds
inputs:
${{ if and(parameters.needsAzurePublicFeeds, eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9')) }}:
nuGetServiceConnections: azure-public/msft_consumption
nuGetServiceConnections: azure-public/msft_consumption_public

- powershell: |
$AccessToken = '$(System.AccessToken)' # Avoid specifying the access token directly on the init.ps1 command line to avoid it showing up in errors
Expand Down
83 changes: 1 addition & 82 deletions doc/analyzers/VSTHRD001.md
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).
46 changes: 1 addition & 45 deletions doc/analyzers/VSTHRD002.md
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).
Loading

0 comments on commit a2f4717

Please sign in to comment.