Refactor hybrid accessors for async
This commit is contained in:
@@ -1,16 +1,41 @@
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
// fixme - must ensure that the ThreadStatic value is properly cleared!
|
||||
internal abstract class HybridAccessorBase<T>
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
protected abstract string HttpContextItemKey { get; }
|
||||
protected abstract string ItemKey { get; }
|
||||
|
||||
[ThreadStatic]
|
||||
private static T _value;
|
||||
// read
|
||||
// http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html
|
||||
// http://stackoverflow.com/questions/14176028/why-does-logicalcallcontext-not-work-with-async
|
||||
// http://stackoverflow.com/questions/854976/will-values-in-my-threadstatic-variables-still-be-there-when-cycled-via-threadpo
|
||||
// https://msdn.microsoft.com/en-us/library/dd642243.aspx?f=255&MSPPError=-2147217396 ThreadLocal<T>
|
||||
// http://stackoverflow.com/questions/29001266/cleaning-up-callcontext-in-tpl clearing call context
|
||||
//
|
||||
// anything that is ThreadStatic will stay with the thread and NOT flow in async threads
|
||||
// the only thing that flows is the logical call context (safe in 4.5+)
|
||||
// now...
|
||||
// tests seem to show that either newing Thread or enqueuing in the ThreadPool both produce a thread
|
||||
// with a clear logical call context, which would mean that it is somewhat safe to "fire and forget"
|
||||
// because whatever is in the call context will be gone when the thread returns to the pool
|
||||
|
||||
// no!
|
||||
//[ThreadStatic]
|
||||
//private static T _value;
|
||||
|
||||
// yes! flows with async!
|
||||
private T NonContextValue
|
||||
{
|
||||
get { return (T) CallContext.LogicalGetData(ItemKey); }
|
||||
set
|
||||
{
|
||||
if (value == null) CallContext.FreeNamedDataSlot(ItemKey);
|
||||
else CallContext.LogicalSetData(ItemKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected HybridAccessorBase(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
@@ -22,8 +47,8 @@ namespace Umbraco.Web
|
||||
get
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null) return _value;
|
||||
return (T) httpContext.Items[HttpContextItemKey];
|
||||
if (httpContext == null) return NonContextValue;
|
||||
return (T) httpContext.Items[ItemKey];
|
||||
}
|
||||
|
||||
set
|
||||
@@ -31,10 +56,10 @@ namespace Umbraco.Web
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
{
|
||||
_value = value;
|
||||
NonContextValue = value;
|
||||
return;
|
||||
}
|
||||
httpContext.Items[HttpContextItemKey] = value;
|
||||
httpContext.Items[ItemKey] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
internal class HybridEventMessagesAccessor : HybridAccessorBase<EventMessages>, IEventMessagesAccessor
|
||||
{
|
||||
protected override string HttpContextItemKey => "Umbraco.Core.Events.EventMessages";
|
||||
protected override string ItemKey => "Umbraco.Core.Events.EventMessages";
|
||||
|
||||
public HybridEventMessagesAccessor(IHttpContextAccessor httpContextAccessor)
|
||||
: base(httpContextAccessor)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
internal class HybridUmbracoContextAccessor : HybridAccessorBase<UmbracoContext>, IUmbracoContextAccessor
|
||||
{
|
||||
protected override string HttpContextItemKey => "Umbraco.Web.UmbracoContext";
|
||||
protected override string ItemKey => "Umbraco.Web.UmbracoContext";
|
||||
|
||||
public HybridUmbracoContextAccessor(IHttpContextAccessor httpContextAccessor)
|
||||
: base(httpContextAccessor)
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
internal class HybridUmbracoDatabaseAccessor : HybridAccessorBase<UmbracoDatabase>, IUmbracoDatabaseAccessor
|
||||
{
|
||||
protected override string HttpContextItemKey => "Umbraco.Core.Persistence.UmbracoDatabase";
|
||||
protected override string ItemKey => "Umbraco.Core.Persistence.UmbracoDatabase";
|
||||
|
||||
public HybridUmbracoDatabaseAccessor(IHttpContextAccessor httpContextAccessor)
|
||||
: base(httpContextAccessor)
|
||||
|
||||
Reference in New Issue
Block a user