## Why is this an issue?

`ValueTask<TResult>` provides a value type that wraps a Task<TResult> and the corresponding `TResult`. It was introduced in .NET Core 2.0 to optimize memory allocation when functions return their results synchronously.

Using `ValueTask` and `ValueTask<TResult>` in the following ways is discouraged as it could result in a race condition:

- Calling `await` multiple times on a `ValueTask`/`ValueTask<TResult>`. The wrapped object may have been reused by another operation. This differs from `Task`/`Task<TResult>`, on which you can await multiple times and always get the same result.
- Calling `await` concurrently on a `ValueTask`/`ValueTask<TResult>`. The underlying object is not thread safe. What’s more, it has the same effect as awaiting multiple times a `ValueTask`/`ValueTask<TResult>`. This again differs from `Task`/`Task<TResult>`, which support concurrent `await`.
- Using `.Result` or `.GetAwaiter().GetResult()` without checking if the operation is completed. `IValueTaskSource`/`IValueTaskSource<TResult>` implementations are not required to block until the operation completes. On the other hand, `Task`/`Task<TResult>` blocks the call until the task completes.

It is recommended to use `ValueTask`/`ValueTask<TResult>` either by calling `await` on the function returning it, optionally calling `ConfigureAwait(false)` on it, or by calling `.AsTask()` on it.

This rule raises an issue when the following operations are performed on a `ValueTask`/`ValueTask<TResult>` instance unless it happens in a loop:

- Awaiting the instance multiple times.
- Calling `AsTask` multiple times.
- Using `.Result` or `.GetAwaiter().GetResult()` multiple times
- Using `.Result` or `.GetAwaiter().GetResult()` when the operation has not yet completed
- Using of these ways to consume the instance multiple times.

## How to fix it

### Code examples

#### Noncompliant code example

    ValueTask<int> vt = ComputeAsync();
    int result = await vt;
    result = await vt; // Noncompliant, variable is awaited multiple times

    int value = ComputeAsync()).GetAwaiter().GetResult(); // Noncompliant, uses GetAwaiter().GetResult() when it's not known to be done

#### Compliant solution

    ValueTask<int> vt = ComputeAsync();
    int result = await vt;

    int value = await ComputeAsync().AsTask();

## Resources

### Documentation

- ValueTask
- ValueTask<TResult>
- Understanding the Whys, Whats, and Whens of ValueTask

### Standards

- STIG Viewer - Application Security and Development: V-222567 - The application must not be vulnerable to race conditions.