Merge pull request #10275 from aspnet/dylan/requestQ
start of request queue
This commit is contained in:
commit
55555bedd5
|
|
@ -83,6 +83,7 @@
|
|||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" RefProjectPath="$(RepoRoot)src\Middleware\Localization\ref\Microsoft.AspNetCore.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" RefProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\ref\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.NodeServices" ProjectPath="$(RepoRoot)src\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj" RefProjectPath="$(RepoRoot)src\Middleware\NodeServices\ref\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.RequestThrottling" ProjectPath="$(RepoRoot)src\Middleware\RequestThrottling\src\Microsoft.AspNetCore.RequestThrottling.csproj" RefProjectPath="$(RepoRoot)src\Middleware\RequestThrottling\ref\Microsoft.AspNetCore.RequestThrottling.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching.Abstractions\src\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj" RefProjectPath="$(RepoRoot)src\Middleware\ResponseCaching.Abstractions\ref\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching\src\Microsoft.AspNetCore.ResponseCaching.csproj" RefProjectPath="$(RepoRoot)src\Middleware\ResponseCaching\ref\Microsoft.AspNetCore.ResponseCaching.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCompression" ProjectPath="$(RepoRoot)src\Middleware\ResponseCompression\src\Microsoft.AspNetCore.ResponseCompression.csproj" RefProjectPath="$(RepoRoot)src\Middleware\ResponseCompression\ref\Microsoft.AspNetCore.ResponseCompression.csproj" />
|
||||
|
|
|
|||
|
|
@ -283,6 +283,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeaderPropagationSample", "
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IIS", "..\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj", "{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RequestThrottling", "RequestThrottling", "{8C9AA8A2-9D1F-4450-9F8D-56BAB6F3D343}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RequestThrottlingSample", "RequestThrottling\sample\RequestThrottlingSample.csproj", "{6720919C-0DEA-49E1-90DC-F1883F7919CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.RequestThrottling", "RequestThrottling\src\Microsoft.AspNetCore.RequestThrottling.csproj", "{4CE2384D-6B88-4824-ADD1-4183D180FEFF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.RequestThrottling.Tests", "RequestThrottling\test\Microsoft.AspNetCore.RequestThrottling.Tests.csproj", "{353AA2B0-1013-486C-B5BD-9379385CA403}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -1541,6 +1549,42 @@ Global
|
|||
{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|x64.Build.0 = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -1663,6 +1707,9 @@ Global
|
|||
{179A159B-87EA-4353-BE92-4FB6CC05BC7D} = {0437D207-864E-429C-92B4-9D08D290188C}
|
||||
{CDE2E736-A034-4748-98C4-0DEDAAC8063D} = {179A159B-87EA-4353-BE92-4FB6CC05BC7D}
|
||||
{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{6720919C-0DEA-49E1-90DC-F1883F7919CD} = {8C9AA8A2-9D1F-4450-9F8D-56BAB6F3D343}
|
||||
{4CE2384D-6B88-4824-ADD1-4183D180FEFF} = {8C9AA8A2-9D1F-4450-9F8D-56BAB6F3D343}
|
||||
{353AA2B0-1013-486C-B5BD-9379385CA403} = {8C9AA8A2-9D1F-4450-9F8D-56BAB6F3D343}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"solution": {
|
||||
"path": "..\\Middleware.sln",
|
||||
"projects": [
|
||||
"..\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj",
|
||||
"..\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj",
|
||||
"..\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj",
|
||||
"..\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj",
|
||||
"..\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj",
|
||||
"..\\Http\\Http.Features\\src\\Microsoft.AspNetCore.Http.Features.csproj",
|
||||
"..\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj",
|
||||
"..\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
|
||||
"..\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj",
|
||||
"..\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj",
|
||||
"..\\Servers\\Kestrel\\Transport.Abstractions\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj",
|
||||
"..\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj",
|
||||
"..\\http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj",
|
||||
"..\\http\\http\\src\\Microsoft.AspNetCore.Http.csproj",
|
||||
"HttpsPolicy\\src\\Microsoft.AspNetCore.HttpsPolicy.csproj",
|
||||
"RequestThrottling\\sample\\RequestThrottlingSample.csproj",
|
||||
"RequestThrottling\\src\\Microsoft.AspNetCore.RequestThrottling.csproj",
|
||||
"RequestThrottling\\test\\Microsoft.AspNetCore.RequestThrottling.Tests.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!-- This file is automatically generated. -->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
||||
<Compile Include="Microsoft.AspNetCore.RequestThrottling.netcoreapp3.0.cs" />
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<Reference Include="Microsoft.AspNetCore.RequestThrottling" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace RequestThrottlingSample
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment environment)
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
await context.Response.WriteAsync("Hello world!");
|
||||
});
|
||||
}
|
||||
|
||||
// Entry point for the application.
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory()) // for the cert file
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
factory.SetMinimumLevel(LogLevel.Debug);
|
||||
factory.AddConsole();
|
||||
})
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware for queuing incoming HTTP requests, to avoid threadpool starvation.</Description>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;queue;queuing</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.RequestThrottling.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.RequestThrottling
|
||||
{
|
||||
internal class SemaphoreWrapper : IDisposable
|
||||
{
|
||||
private SemaphoreSlim _semaphore;
|
||||
|
||||
public SemaphoreWrapper(int queueLength)
|
||||
{
|
||||
_semaphore = new SemaphoreSlim(queueLength);
|
||||
}
|
||||
|
||||
public Task EnterQueue()
|
||||
{
|
||||
return _semaphore.WaitAsync();
|
||||
}
|
||||
|
||||
public void LeaveQueue()
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get => _semaphore.CurrentCount;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_semaphore.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.RequestThrottling" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Xunit;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.AspNetCore.RequestThrottling.Tests
|
||||
{
|
||||
public class SemaphoreWrapperTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task TracksQueueLength()
|
||||
{
|
||||
using var s = new SemaphoreWrapper(1);
|
||||
Assert.Equal(1, s.Count);
|
||||
|
||||
await s.EnterQueue().OrTimeout();
|
||||
Assert.Equal(0, s.Count);
|
||||
|
||||
s.LeaveQueue();
|
||||
Assert.Equal(1, s.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesNotWaitIfSpaceAvailible()
|
||||
{
|
||||
using var s = new SemaphoreWrapper(2);
|
||||
|
||||
var t1 = s.EnterQueue();
|
||||
Assert.True(t1.IsCompleted);
|
||||
|
||||
var t2 = s.EnterQueue();
|
||||
Assert.True(t2.IsCompleted);
|
||||
|
||||
var t3 = s.EnterQueue();
|
||||
Assert.False(t3.IsCompleted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WaitsIfNoSpaceAvailible()
|
||||
{
|
||||
using var s = new SemaphoreWrapper(1);
|
||||
await s.EnterQueue().OrTimeout();
|
||||
|
||||
var waitingTask = s.EnterQueue();
|
||||
Assert.False(waitingTask.IsCompleted);
|
||||
|
||||
s.LeaveQueue();
|
||||
await waitingTask.OrTimeout();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IsEncapsulated()
|
||||
{
|
||||
using var s1 = new SemaphoreWrapper(1);
|
||||
using var s2 = new SemaphoreWrapper(1);
|
||||
|
||||
await s1.EnterQueue().OrTimeout();
|
||||
await s2.EnterQueue().OrTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
#if TESTUTILS
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class TaskExtensions
|
||||
{
|
||||
private const int DefaultTimeout = 30 * 1000;
|
||||
|
||||
public static Task OrTimeout(this Task task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null)
|
||||
{
|
||||
return OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber);
|
||||
}
|
||||
|
||||
public static Task OrTimeout(this Task task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null)
|
||||
{
|
||||
return task.TimeoutAfter(timeout, filePath, lineNumber ?? 0);
|
||||
}
|
||||
|
||||
public static Task<T> OrTimeout<T>(this ValueTask<T> task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) =>
|
||||
OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber);
|
||||
|
||||
public static Task<T> OrTimeout<T>(this ValueTask<T> task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null) =>
|
||||
task.AsTask().OrTimeout(timeout, memberName, filePath, lineNumber);
|
||||
|
||||
public static Task<T> OrTimeout<T>(this Task<T> task, int milliseconds = DefaultTimeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null)
|
||||
{
|
||||
return OrTimeout(task, new TimeSpan(0, 0, 0, 0, milliseconds), memberName, filePath, lineNumber);
|
||||
}
|
||||
|
||||
public static Task<T> OrTimeout<T>(this Task<T> task, TimeSpan timeout, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int? lineNumber = null)
|
||||
{
|
||||
return task.TimeoutAfter(timeout, filePath, lineNumber ?? 0);
|
||||
}
|
||||
|
||||
public static async Task OrThrowIfOtherFails(this Task task, Task otherTask)
|
||||
{
|
||||
var completed = await Task.WhenAny(task, otherTask);
|
||||
if (completed == otherTask && otherTask.IsFaulted)
|
||||
{
|
||||
// Manifest the exception
|
||||
otherTask.GetAwaiter().GetResult();
|
||||
throw new Exception("Unreachable code");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Await the task we were asked to await. Either it's finished, or the otherTask finished successfully, and it's not our job to check that
|
||||
await task;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<T> OrThrowIfOtherFails<T>(this Task<T> task, Task otherTask)
|
||||
{
|
||||
await OrThrowIfOtherFails((Task)task, otherTask);
|
||||
|
||||
// If we get here, 'task' is finished and succeeded.
|
||||
return task.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@ECHO OFF
|
||||
SET RepoRoot=%~dp0..\..
|
||||
%RepoRoot%\build.cmd -projects %~dp0\**\*.*proj %*
|
||||
Loading…
Reference in New Issue