Skip to content

Commit d86be87

Browse files
authored
Enable CA2012 (Use ValueTask Correctly) (#31221)
1 parent f5feab7 commit d86be87

File tree

17 files changed

+61
-65
lines changed

17 files changed

+61
-65
lines changed

.editorconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@ charset = utf-8-bom
7272
[*.{cs,vb}]
7373
# CA1305: Specify IFormatProvider
7474
dotnet_diagnostic.CA1305.severity = error
75+
76+
[*.{cs,vb}]
77+
# CA2012: Use ValueTask correctly
78+
dotnet_diagnostic.CA2012.severity = warning
79+
[**/{test,perf}/**.{cs,vb}]
80+
dotnet_diagnostic.CA2012.severity = suggestion

src/Components/Components/src/Routing/Router.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private void OnLocationChanged(object sender, LocationChangedEventArgs args)
267267
_locationAbsolute = args.Location;
268268
if (_renderHandle.IsInitialized && Routes != null)
269269
{
270-
_ = RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted);
270+
_ = RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted).Preserve();
271271
}
272272
}
273273

src/Components/Server/src/Circuits/RemoteNavigationManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected override void NavigateToCore(string uri, bool forceLoad)
7575
throw new NavigationException(absoluteUriString);
7676
}
7777

78-
_jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad);
78+
_jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad).Preserve();
7979
}
8080

8181
private static class Log

src/Hosting/Hosting/src/Internal/WebHost.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ public async Task StopAsync(CancellationToken cancellationToken = default)
334334

335335
public void Dispose()
336336
{
337-
DisposeAsync().GetAwaiter().GetResult();
337+
DisposeAsync().AsTask().GetAwaiter().GetResult();
338338
}
339339

340340
public async ValueTask DisposeAsync()

src/Http/Http/src/Features/RequestServicesFeature.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static async ValueTask Awaited(RequestServicesFeature servicesFeature, ValueTask
8787
/// <inheritdoc />
8888
public void Dispose()
8989
{
90-
DisposeAsync().GetAwaiter().GetResult();
90+
DisposeAsync().AsTask().GetAwaiter().GetResult();
9191
}
9292
}
9393
}

src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ internal class Http1OutputProducer : IHttpOutputProducer, IDisposable
5858

5959
private bool _autoChunk;
6060

61-
// We rely on the TimingPipeFlusher to give us ValueTasks that can be safely awaited multiple times.
6261
private bool _writeStreamSuffixCalled;
63-
private ValueTask<FlushResult> _writeStreamSuffixValueTask;
6462

6563
private int _advancedBytesForChunk;
6664
private Memory<byte> _currentChunkMemory;
@@ -118,31 +116,27 @@ public ValueTask<FlushResult> WriteDataToPipeAsync(ReadOnlySpan<byte> buffer, Ca
118116

119117
public ValueTask<FlushResult> WriteStreamSuffixAsync()
120118
{
119+
ValueTask<FlushResult> result = default;
120+
121121
lock (_contextLock)
122122
{
123-
if (_writeStreamSuffixCalled)
123+
if (!_writeStreamSuffixCalled)
124124
{
125-
// If WriteStreamSuffixAsync has already been called, no-op and return the previously returned ValueTask.
126-
return _writeStreamSuffixValueTask;
127-
}
125+
if (_autoChunk)
126+
{
127+
var writer = new BufferWriter<PipeWriter>(_pipeWriter);
128+
result = WriteAsyncInternal(ref writer, EndChunkedResponseBytes);
129+
}
130+
else if (_unflushedBytes > 0)
131+
{
132+
result = FlushAsync();
133+
}
128134

129-
if (_autoChunk)
130-
{
131-
var writer = new BufferWriter<PipeWriter>(_pipeWriter);
132-
_writeStreamSuffixValueTask = WriteAsyncInternal(ref writer, EndChunkedResponseBytes);
133-
}
134-
else if (_unflushedBytes > 0)
135-
{
136-
_writeStreamSuffixValueTask = FlushAsync();
137-
}
138-
else
139-
{
140-
_writeStreamSuffixValueTask = default;
135+
_writeStreamSuffixCalled = true;
141136
}
142-
143-
_writeStreamSuffixCalled = true;
144-
return _writeStreamSuffixValueTask;
145137
}
138+
139+
return result;
146140
}
147141

148142
public ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = default)
@@ -533,7 +527,6 @@ public void Reset()
533527
_currentMemoryPrefixBytes = 0;
534528
_autoChunk = false;
535529
_writeStreamSuffixCalled = false;
536-
_writeStreamSuffixValueTask = default;
537530
_currentChunkMemoryUpdated = false;
538531
_startCalled = false;
539532
}

src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,15 @@ public void ProduceContinue()
917917
((IHeaderDictionary)HttpRequestHeaders).TryGetValue(HeaderNames.Expect, out var expect) &&
918918
(expect.FirstOrDefault() ?? "").Equals("100-continue", StringComparison.OrdinalIgnoreCase))
919919
{
920-
Output.Write100ContinueAsync().GetAwaiter().GetResult();
920+
ValueTask<FlushResult> vt = Output.Write100ContinueAsync();
921+
if (vt.IsCompleted)
922+
{
923+
vt.GetAwaiter().GetResult();
924+
}
925+
else
926+
{
927+
vt.AsTask().GetAwaiter().GetResult();
928+
}
921929
}
922930
}
923931

@@ -1050,6 +1058,8 @@ private Task WriteSuffix()
10501058
return WriteSuffixAwaited(writeTask);
10511059
}
10521060

1061+
writeTask.GetAwaiter().GetResult();
1062+
10531063
_requestProcessingStatus = RequestProcessingStatus.ResponseCompleted;
10541064

10551065
if (_keepAlive)

src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/StreamInputFlowControl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void UpdateWindows(int bytes)
5757
if (streamWindowUpdateSize > 0)
5858
{
5959
// Writing with the FrameWriter should only fail if given a canceled token, so just fire and forget.
60-
_ = _frameWriter.WriteWindowUpdateAsync(StreamId, streamWindowUpdateSize);
60+
_ = _frameWriter.WriteWindowUpdateAsync(StreamId, streamWindowUpdateSize).Preserve();
6161
}
6262

6363
UpdateConnectionWindow(bytes);
@@ -90,7 +90,7 @@ private void UpdateConnectionWindow(int bytes)
9090
if (connectionWindowUpdateSize > 0)
9191
{
9292
// Writing with the FrameWriter should only fail if given a canceled token, so just fire and forget.
93-
_ = _frameWriter.WriteWindowUpdateAsync(0, connectionWindowUpdateSize);
93+
_ = _frameWriter.WriteWindowUpdateAsync(0, connectionWindowUpdateSize).Preserve();
9494
}
9595
}
9696
}

src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public void Abort(ConnectionAbortedException ex)
157157
{
158158
if (TryClose())
159159
{
160-
_frameWriter.WriteGoAwayAsync(int.MaxValue, Http2ErrorCode.INTERNAL_ERROR);
160+
_frameWriter.WriteGoAwayAsync(int.MaxValue, Http2ErrorCode.INTERNAL_ERROR).Preserve();
161161
}
162162

163163
_frameWriter.Abort(ex);
@@ -1214,7 +1214,7 @@ private void UpdateConnectionState()
12141214

12151215
if (_gracefulCloseInitiator == GracefulCloseInitiator.Server && _clientActiveStreamCount > 0)
12161216
{
1217-
_frameWriter.WriteGoAwayAsync(int.MaxValue, Http2ErrorCode.NO_ERROR);
1217+
_frameWriter.WriteGoAwayAsync(int.MaxValue, Http2ErrorCode.NO_ERROR).Preserve();
12181218
}
12191219
}
12201220

@@ -1224,7 +1224,7 @@ private void UpdateConnectionState()
12241224
{
12251225
if (TryClose())
12261226
{
1227-
_frameWriter.WriteGoAwayAsync(_highestOpenedStreamId, Http2ErrorCode.NO_ERROR);
1227+
_frameWriter.WriteGoAwayAsync(_highestOpenedStreamId, Http2ErrorCode.NO_ERROR).Preserve();
12281228
}
12291229
}
12301230
else

src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ internal class Http2OutputProducer : IHttpOutputProducer, IHttpOutputAborter, IV
4343
private bool _writerComplete;
4444

4545
// Internal for testing
46-
internal ValueTask _dataWriteProcessingTask;
46+
internal Task _dataWriteProcessingTask;
4747
internal bool _disposed;
4848

4949
/// <summary>The core logic for the IValueTaskSource implementation.</summary>
@@ -394,7 +394,7 @@ public void Reset()
394394
{
395395
}
396396

397-
private async ValueTask ProcessDataWrites()
397+
private async Task ProcessDataWrites()
398398
{
399399
// ProcessDataWrites runs for the lifetime of the Http2OutputProducer, and is designed to be reused by multiple streams.
400400
// When Http2OutputProducer is no longer used (e.g. a stream is aborted and will no longer be used, or the connection is closed)

0 commit comments

Comments
 (0)