microsoft / microsoft/vs-threading

NoMainThreadDependencyAttribute

Open
#475 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

analyzers
Dominant language
C#
Stars
1k
Forks
160
Avg merge
1d 12h
Merged PRs (30d)
28

Description

Is your feature request related to a problem? Please describe.

JTF (and its overhead) can be avoided when joining tasks started in an unknown context if the code is known to not have any dependencies on the main thread. Currently there is no way to document or validate these expectations.

Describe the solution you'd like

It should be possible to apply an attribute, e.g. [NoMainThreadDependency], to asynchronous operations that by contract never depend on the main thread for completion.

Rules:

  1. Asynchronous code with this attribute would only be allowed to call other asynchronous code that was also marked with this attribute.
  2. Asynchronous code with this attribute must use ConfigureAwait(false).
    • Do we want to have a CapturesContext property which allows the use of ConfigureAwait(true), but does offer the dependency guarantee if execution starts in the thread pool? I hit one case so far in Roslyn where this occurred.
  3. Asynchronous code with this attribute must not use SwitchToMainThreadAsync.
  4. Asynchronous code cannot implement or override a method marked with this attribute unless it is also marked with this attribute. However, specific implementations are allowed to place additional restrictions.
  5. The gate used for a lock statement must be marked with this attribute. Analysis cannot guarantee correct usage, but it can guarantee correct documentation of claims.
  6. An analyzer (disabled by default) would report cases where a synchronous method calls JoinableTaskFactory.Run but was not marked with either [AsyncEntry] or [NoMainThreadDependency].
  7. If an instance of a type is marked with [NoMainThreadDependency] (e.g. the attribute is placed on a field), methods on the type annotated with [NoMainThreadDependency(PerInstance = true)] would be considered to not have a main thread dependency. This will enable instances of Roslyn's AsyncLazy<T> to be marked as not having a main thread dependency, and only for those instances would constraints appear on the constructor parameter and GetValueAsync.

Distribution:

The attributes for this analyzer would be injected as internal types when the analyzer package is installed in a project, similar to the behavior of PerformanceSensitiveAnalyzers. Since the attribute feeds cross-assembly analysis, it would not be [Conditional].

Describe alternatives you've considered

Using JoinableTask<T>.JoinAsync instead of await.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the analyzer package and the existing PerformanceSensitiveAnalyzers attribute-injection behavior mentioned in the issue. Map the proposed NoMainThreadDependency rules, including the unresolved CapturesContext question, and define the analyzer, injected attributes, and validation behavior needed for the documented cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.