IT TIP

AsyncLocal의 의미는 논리적 호출 컨텍스트와 어떻게 다릅니 까?

itqueen 2020. 12. 25. 10:41
반응형

AsyncLocal의 의미는 논리적 호출 컨텍스트와 어떻게 다릅니 까?


.NET 4.6 AsyncLocal<T>에는 비동기 제어 흐름을 따라 주변 데이터를 흐름을위한 클래스가 도입되었습니다 . 나는 이전 CallContext.LogicalGet/SetData에이 목적으로 사용 했으며, 두 가지가 의미 론적으로 다른지 그리고 어떤 방식으로 (강력한 타이핑과 문자열 키에 대한 의존성 부족과 같은 명백한 API 차이를 넘어서) 궁금합니다.


의미는 거의 동일합니다. 둘 다에 저장되고 ExecutionContext비동기 호출을 통해 흐릅니다.

차이점은 API 변경 (설명한대로)과 값 변경에 대한 콜백을 등록하는 기능입니다.

기술적 CallContext으로는 의 데이터가 사전에 보관되고 추가 작업없이 해당 참조 만 복사 CallContext.Clone되는 동안 복사 (사용 ) 할 때마다 복제되므로 구현에 큰 차이 있습니다.AsyncLocalExecutionContext._localValues

AsyncLocal의 값 을 변경할 때 업데이트가 현재 흐름에만 영향을 미치도록하기 위해 새 사전이 생성되고 모든 기존 값이 새 사전에 얕게 복사됩니다.

이 차이 AsyncLocal는 사용되는 위치에 따라 성능에 좋을 수도 있고 나쁠 수도 있습니다 .

이제 주석에서 언급 한 Hans Passant CallContext는 원래 원격 용으로 만들어졌고 원격 기능이 지원되지 않는 곳에서는 사용할 수 없습니다 (예 : .Net Core). 아마 AsyncLocal프레임 워크에 추가 된 이유 일 것입니다 .

#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

참고 : AsyncLocalVisual Studio SDK에는 기본적으로 CallContext개념이 얼마나 유사한 지 보여주는 래퍼 인 Microsoft.VisualStudio.Threading이 있습니다.


두 가지 의미가 다른지 그리고 어떤 방식으로 다른지 궁금합니다.

볼, 모두 할 수있는 일에서 CallContextAsyncLocal의존 내부적으로 ExecutionContext돌며 자신의 내부 데이터를 저장합니다 Dictionary. 후자는 비동기 호출에 대한 또 다른 수준의 간접적 인 방향을 추가하는 것 같습니다. CallContext.NET Remoting 이후로 존재했으며 지금까지 실제 대안이 없었던 비동기 호출간에 데이터를 이동하는 편리한 방법이었습니다.

내가 발견 할 수있는 가장 큰 차이점은 AsyncLocal이제 기본 저장된 값이 ExecutionContext스위치에 의해 변경 되거나 기존 값을 대체하여 명시 적으로 변경 될 때 콜백을 통해 알림에 등록 할 수 있다는 것 입니다.

// AsyncLocal<T> also provides optional notifications 
// when the value associated with the current thread
// changes, either because it was explicitly changed 
// by setting the Value property, or implicitly changed
// when the thread encountered an "await" or other context transition.
// For example, we might want our
// current culture to be communicated to the OS as well:

static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>(
args =>
{
    NativeMethods.SetThreadCulture(args.CurrentValue.LCID);
});

그 외에 하나는에 System.Threading있고 다른 하나는에 있으며 System.Runtime.Remoting전자는 CoreCLR에서 지원됩니다.

또한 AsyncLocal얕은 copy-on-write 의미론 SetLogicalData있는 것 같지 않으므로 데이터가 복사되지 않고 호출간에 흐릅니다.


타이밍에 의미 론적 차이가있는 것 같습니다.

CallContext를 사용하면 자식 스레드 / 태스크 / 비동기 메서드에 대한 컨텍스트가 설정 될 때 (예 : Task.Factory.StartNew (), Task.Run () 또는 비동기 메서드가 호출 될 때) 컨텍스트 변경이 발생합니다.

AsyncLocal을 사용하면 자식 스레드 / 태스크 / 비동기 메서드가 실제로 실행을 시작할 때 컨텍스트 변경 (변경 알림 콜백 호출)이 발생합니다.

특히 컨텍스트가 전환 될 때 컨텍스트 개체를 복제하려는 경우 타이밍 차이가 흥미로울 수 있습니다. 다른 메커니즘을 사용하면 다른 콘텐츠가 복제 될 수 있습니다. CallContext를 사용하면 자식 스레드 / 태스크가 생성되거나 비동기 메서드가 호출 될 때 콘텐츠를 복제합니다. 그러나 AsyncLocal을 사용하면 자식 스레드 / 태스크 / 비동기 메서드가 실행을 시작할 때 콘텐츠를 복제하면 컨텍스트 개체의 콘텐츠가 부모 스레드에 의해 변경 될 수 있습니다.

참조 URL : https://stackoverflow.com/questions/31707362/how-do-the-semantics-of-asynclocal-differ-from-the-logical-call-context

반응형