首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >操作取消

操作取消
EN

Code Review用户
提问于 2019-10-02 05:26:07
回答 1查看 411关注 0票数 9

简洁适用于国王,因为它需要上下文,而上下文则适用于国王。我。

GitHubNuGet

您已经写了多少次这样的东西,传递那些乏味的记录器/令牌参数?

代码语言:javascript
复制
interface IMyService
{
    void Method1(…, ILogger logger, CancellationToken token);
    void Method2(…, ILogger logger, CancellationToken token);
    …
}

够了够了。有关环境日志记录,请参见这里。下面是关于环境取消。

我们将要做的是使用一个特殊的Cancellation助手类,如下所示:

代码语言:javascript
复制
    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被定义为:

代码语言:javascript
复制
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();        
}
EN

回答 1

Code Review用户

发布于 2019-10-03 06:18:16

不确定它是否可以算作答案,但最重要的缺失部分是以下ASP.NET核心属性:

代码语言:javascript
复制
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();
    }
}
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/230014

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档