简洁适用于国王,因为它需要上下文,而上下文则适用于国王。我。
您已经写了多少次这样的东西,传递那些乏味的记录器/令牌参数?
interface IMyService
{
void Method1(…, ILogger logger, CancellationToken token);
void Method2(…, ILogger logger, CancellationToken token);
…
}够了够了。有关环境日志记录,请参见这里。下面是关于环境取消。
我们将要做的是使用一个特殊的Cancellation助手类,如下所示:
static void Main(string[] args)
{
using (new Cancellation())
{
Task.Run(PingAsync);
ReadLine();
Cancellation.Request();
ReadLine();
}
}
static async Task PingAsync()
{
try
{
while (!Cancellation.Requested)
{
await Task.Delay(100, Cancellation.Token);
WriteLine("Ping");
}
Cancellation.ThrowIfRequested();
}
catch(OperationCanceledException)
{
WriteLine("Ping cancelled");
}
}其中Cancellation被定义为:
public class Cancellation : IDisposable
{
static AsyncLocal<CancellationTokenSource> Context { get; } =
new AsyncLocal<CancellationTokenSource>();
public Cancellation()
: this(CancellationToken.None)
{
}
public Cancellation(CancellationToken cancellationToken)
: this(cancellationToken, Timeout.InfiniteTimeSpan)
{
}
public Cancellation(int timeout)
: this(TimeSpan.FromMilliseconds(timeout))
{
}
public Cancellation(TimeSpan timeout)
: this(CancellationToken.None, timeout)
{
}
public Cancellation(CancellationToken cancellationToken, int timeout)
: this(cancellationToken, TimeSpan.FromMilliseconds(timeout))
{
}
public Cancellation(CancellationToken cancellationToken, TimeSpan timeout)
{
Parent = Context.Value;
Context.Value = CancellationTokenSource
.CreateLinkedTokenSource(cancellationToken);
Context.Value.CancelAfter(timeout);
}
public void Dispose()
{
var cts = Context.Value;
Context.Value = Parent;
cts.Dispose();
}
CancellationTokenSource Parent { get; }
public static CancellationToken Token =>
Context.Value?.Token ?? CancellationToken.None;
public static void Request() => Context.Value?.Cancel();
public static bool Requested => Token.IsCancellationRequested;
public static void ThrowIfRequested() => Token.ThrowIfCancellationRequested();
}发布于 2019-10-03 06:18:16
不确定它是否可以算作答案,但最重要的缺失部分是以下ASP.NET核心属性:
public class AmbientContextAttribute : Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
using (new Op(context.HttpContext.Request.GetDisplayUrl()))
using (new Cancellation(context.HttpContext.RequestAborted))
await next();
}
}https://codereview.stackexchange.com/questions/230014
复制相似问题