2016-09-29 6 views
0

비싼 리소스의 초기화를 보호하기 위해 Stephen Cleary의 Nito.AsyncEx NuGet 패키지 (v3.0.1)의 AsyncLock을 사용 중이므로 첫 번째 호출자 만 수행합니다 시간 소모적 인 비동기 초기화 및 모든 후속 호출자는 초기화가 완료 될 때까지 비동기 적으로 대기 한 다음 캐시 된 리소스를 가져옵니다.Nito.AsyncEx.AsyncLock 스택 오버플로가 많은 대기자 및 동기식 고속 경로

내가 먼저 발견하는 것은 AsyncLock에 의해 보호 지역을 다음과 같은 코드가 작업에 시작된 정확한 역순으로 작업에서 실행 된 것입니다 (즉, 마지막 작업은 먼저 락 영역을지나 계속 가지고 시작 , 마지막 두 번째 작업, 마지막 작업이 끝날 때까지 계속됩니다).

그런 다음 왜 그런 일이 발생했는지 조사하는 과정에서 많은 수의 비동기 작업이있을 때 일관되게 스택 오버플로가 발생한다는 것을 발견했습니다. 여기에 간단한 예입니다 : GetFooAsync()을 통해 빠른 경로가 동기가 아닌 경우

object _foo; 
readonly Nito.AsyncEx.AsyncLock _fooLock = new Nito.AsyncEx.AsyncLock(); 

async Task<object> GetFooAsync() 
{ 
    using (await _fooLock.LockAsync().ConfigureAwait(false)) 
    { 
     if (_foo == null) 
     { 
      // Simulate time-consuming asynchronous initialization, 
      // during which all the subsequent tasks end up awaiting the AsyncLock. 
      await Task.Delay(5000).ConfigureAwait(false); 
      _foo = new object(); 
     } 
     return _foo; 
    } 
} 

async Task DoStuffAsync() 
{ 
    object foo = await GetFooAsync().ConfigureAwait(false); 
    // Do stuff with foo... 
} 

void DoStuff() 
{ 
    var tasks = new List<Task>(); 

    for (int i = 1; i <= 1000; i++) 
    { 
     tasks.Add(DoStuffAsync()); 
    } 

    Task.WhenAll(tasks).Wait(); 
} 

(예를 들어 나는 await Task.Yield(); 바로 return _foo; 전에를 추가하는 경우) 다음뿐만 아니라 스택 오버 플로우가 발생하지 않지만, 작업은 잠긴 지역을지나 계속

테스트 한 적이 있고이 문제가 발생하지 않는 것으로 보이는이 사용 사례 대신 AsyncEx에서 AsyncLazy<T>을 사용하도록 코드를 변경하고있을 것입니다.

그러나이 문제가 내 코드의 실수로 인한 것인가, 아니면 AsyncLock의 버그인지, 아니면 그냥 예상되는 동작 (잡다한 것)인지 알고 싶습니다.

답변

3

그것은 bug in AsyncLock입니다. 모든 대기열 기반 비동기 조정 프리미티브에는 동일한 문제가 있습니다. 수정 프로그램이 작동 중입니다.

new version of this library에는이 문제가없는 다시 작성된 큐가 있습니다.

+0

빠른 답변 감사드립니다. 고칠 수있을 때 어떤 생각? 아니면 그 일을 도울 수있는 일이 있습니까? 새 버전을 사용하고 싶지만 코드를 실행해야하는 시스템은 현재 .NET 4.5로 고정되어 있으며 새 버전에는 .NET 4.6이 필요합니다. –

+0

지연은 WP7.1 및 SL4와 같은 하위 플랫폼을 지원하는 빌드 시스템이 없기 때문에 지연됩니다. 나는 더 새로운 문제에 대해서만 빌드를 진행하기로 결정했기 때문에 이것은'4.x' 버전이 될 것입니다. 희망적으로 이번 주말에 어느 시점에. 새 버전에는 net46이 필요합니다. 새로운 비동기식 대기열에 필요합니다. –