Task.AsCancellable

This commit is contained in:
Timerix 2025-03-23 00:09:40 +05:00
parent 7d814ee4cb
commit dc35725b64
4 changed files with 42 additions and 4 deletions

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<!--package info-->
<PackageId>DTLib.Web</PackageId>
<Version>1.1.0</Version>
<Version>1.1.1</Version>
<Authors>Timerix</Authors>
<Description>HTTP Server with simple routing</Description>
<RepositoryType>GIT</RepositoryType>
@ -25,6 +25,6 @@
<ProjectReference Include="..\DTLib\DTLib.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' != 'Debug' ">
<PackageReference Include="DTLib" Version="1.6.*" />
<PackageReference Include="DTLib" Version="1.6.4" />
</ItemGroup>
</Project>

View File

@ -6,6 +6,7 @@ global using System.Threading.Tasks;
global using DTLib.Filesystem;
global using DTLib.Logging;
global using System.Net;
using DTLib.Extensions;
using DTLib.Web.Routes;
namespace DTLib.Web;
@ -35,7 +36,7 @@ public class WebApp
long requestId = 1;
while (!_stopToken.IsCancellationRequested)
{
var ctx = await server.GetContextAsync();
var ctx = await server.GetContextAsync().AsCancellable(_stopToken);
HandleRequestAsync(ctx, requestId);
requestId++;
}

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<!--package info-->
<PackageId>DTLib</PackageId>
<Version>1.6.3</Version>
<Version>1.6.4</Version>
<Authors>Timerix</Authors>
<Description>Library for all my C# projects</Description>
<RepositoryType>GIT</RepositoryType>

View File

@ -0,0 +1,37 @@
namespace DTLib.Extensions;
public static class TaskExtensions
{
// https://stackoverflow.com/a/69861689
public static Task<T> AsCancellable<T>(this Task<T> task, CancellationToken token)
{
if (!token.CanBeCanceled)
{
return task;
}
var tcs = new TaskCompletionSource<T>();
// This cancels the returned task:
// 1. If the token has been canceled, it cancels the TCS straightaway
// 2. Otherwise, it attempts to cancel the TCS whenever
// the token indicates cancelled
token.Register(() => tcs.TrySetCanceled(token),
useSynchronizationContext: false);
task.ContinueWith(t =>
{
// Complete the TCS per task status
// If the TCS has been cancelled, this continuation does nothing
if (task.IsCanceled)
tcs.TrySetCanceled();
else if (task.IsFaulted)
tcs.TrySetException(t.Exception!);
else tcs.TrySetResult(t.Result);
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
return tcs.Task;
}
}