Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
554 views
in Technique[技术] by (71.8m points)

c# - How do the semantics of AsyncLocal differ from the logical call context?

.NET 4.6 introduces the AsyncLocal<T> class for flowing ambient data along the asynchronous flow of control. I've previously used CallContext.LogicalGet/SetData for this purpose, and I'm wondering if and in what ways the two are semantically different (beyond the obvious API differences like strong typing and lack of reliance on string keys).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The semantics are pretty much the same. Both are stored in the ExecutionContext and flow through async calls.

The differences are API changes (just as you described) together with the ability to register a callback for value changes.

Technically, there's a big difference in the implementation as the CallContext is cloned each time it is copied (using CallContext.Clone) while the AsyncLocal's data is kept in the ExecutionContext._localValues dictionary and just that reference is copied over without any extra work.

To make sure updates only affect the current flow when you change the AsyncLocal's value a new dictionary is created and all the existing values are shallow-copied to the new one.

That difference can be both good and bad for performance, depending on where the AsyncLocal is used.

Now, as Hans Passant mentioned in the comments CallContext was originally made for remoting, and isn't available where remoting isn't supported (e.g. .Net Core) which is probably why AsyncLocal was added to the framework:

#if FEATURE_REMOTING
    public LogicalCallContext.Reader LogicalCallContext 
    {
        [SecurityCritical]
        get { return new LogicalCallContext.Reader(IsNull ? null : m_ec.LogicalCallContext); } 
    }

    public IllogicalCallContext.Reader IllogicalCallContext 
    {
        [SecurityCritical]
        get { return new IllogicalCallContext.Reader(IsNull ? null : m_ec.IllogicalCallContext); } 
    }
#endif

Note: there's also an AsyncLocal in the Visual Studio SDK that is basically a wrapper over CallContext which shows how similar the concepts are: Microsoft.VisualStudio.Threading.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...