2017-07-21 29 views
2

我有使用中间件像这样的请求管道设置自定义执行上下文的WebAPI:如何在ASP .NET Core请求管道中仍然有未完成的子线程时停止线程重用?

public async Task Invoke(HttpContext httpContext) 
{ 
    using (Context.With(new TokenContext("token"))) 
    { 
    await _next(httpContext); 
    } 
} 

和上下文管理器看起来有点像这样与IContext对象是本地的一叠当前线程(以及它创建的线程)。

public static class Context 
{ 
    private static AsyncLocal<Stack<IContext>> _current = new AsyncLocal<Stack<IContext>>(); 
    public static IContext Current 
    { 
    get 
    { 
     return _current.Value != null && _current.Value.Count > 0 ?_current.Value.Peek() : null; 
    } 
    } 

    public static IDisposable With(IContext context) 
    { 
    Assert.IsNotNull(context); 

    if (_current.Value == null) _current.Value = new Stack<IContext>(); 
    _current.Value.Push(context); 

    return new DelegateDisposable(() => 
    { 
     _current.Value.Pop(); 
    }); 
    } 
} 

我遇到的问题是当有多个请求在同一时间进行。有时我遇到的问题不是我所期望的。我注意到在使用using语句设置它之前,当前上下文有时已经有了一个值。我的结论是,用于请求的初始线程在遇到await _next行时会返回到线程池,并且此线程可以重新用于以下请求,这些请求有时在“子线程”完成之前发生。这给我留下了很多不可预知的行为。

所以,我的问题:我该如何调整这个,使我不会遇到这个问题?我可以强制请求管道在所有“子线程”完成之前不返回线程吗?这会效率低下吗?我可以强制“母线程”在它将自身返回到池之前清理它对上下文堆栈的引用吗?

还有其他的选择吗?

回答

1

这从the documentation,而不是明显的,但the types stored in AsyncLocal<T> should be immutable

这应该清理你的问题(使用ImmutableStack from NuGet):

public static class Context 
{ 
    private static AsyncLocal<ImmutableStack<IContext>> _local = new AsyncLocal<ImmutableStack<IContext>>(); 
    private static ImmutableStack<IContext> Value => _local.Value ?? ImmutableStack<IContext>.Empty; 
    public static IContext Current 
    { 
    get 
    { 
     var value = Value; 
     return value.IsEmpty ? null : value.Peek(); 
    } 
    } 

    public static IDisposable With(IContext context) 
    { 
    Assert.IsNotNull(context); 

    _local.Value = Value.Push(context); 

    return new DelegateDisposable(() => 
    { 
     _local.Value = Value.Pop(); 
    }); 
    } 
} 

的关键是,所有的修改(包括push和pop)必须设置AsyncLocal<T>.Value。这可以使用常规的Stack<T>来完成,但是使用ImmutableStack<T>会强制使用正确的语义。

+0

谢谢,它的工作! –

相关问题