2017-12-21 18 views
0

.NET Framework 4.7.1에서 실행되는 ASP.NET MVC 5 웹 응용 프로그램이 있습니다. 때때로 시작 우리는 서비스의 메소드를 호출 컨트롤러의 행동 내부작업 완료 후 ASP.NET MVC 응용 프로그램이 응답하지 않습니다.

새로운 Task과 같이 :

컨트롤러 :

public async Task<ActionResult> Index() 
{ 
    Info info = await this.someService.GetInformationAsync().ConfigureAwait(false); 
    return this.ProcessInfo(info); 
} 

SomeService (Global.asax 내부 static 개체로 존재) :

private readonly Object taskLock = new Object(); 
private Task errorCheckerTask; 

public Task<Info> GetInformationAsync() 
{ 
    try 
    { 
     ... 
    } 
    catch(Exception ex) 
    { 
     this.StartErrorChecker(); 
    } 

    return null; 
} 

private void StartErrorChecker() 
{ 
    lock(this.taskLock) 
    { 
     if(this.errorCheckerTask == null || this.errorCheckerTask.Status >= TaskStatus.RanToCompletion) 
     { 
      this.errorCheckerTask = this.BeginErrorCheckerAsync(CancellationToken.None); 
     } 
    } 
} 

private async Task BeginErrorCheckerAsync(CancellationToken ct) 
{ 
    while(!ct.IsCancellationRequested) 
    { 
     Boolean ok = await DoStuff(); 
     if(ok) return; 
     await Task.Delay(30 * 1000).ConfigureAwait(false); 
    } 
} 

BeginErrorCheckerAsync 작업을 처음 시작한 후에는 정상적으로 작동합니다. BeginErrorCheckerAsync이 두 번째로 실행되면 Visual Studio의 Output 창에 스레드가 끊어지고 웹 응용 프로그램이 새로운 HTTP 요청에 응답하지 않습니다. 모든 브라우저는 요청을 보낸 후에 응답을 기다리고 있다고 말합니다.

중단 단추를 누르면 Visual Studio Threads 창에 실행중인 스레드가 하나도 표시되지 않고 스택 추적에 사용자 코드가 없습니다.

스레드 0x5440은 코드 0 (0x0으로)로 종료했습니다

중요한 것은, 어떤 첫 번째 예외가 발생하거나 이상한 출력 스레드에 대한 메시지 외에 출력 창에 표시했다. 스레드 0x547c가 코드 0 (0x0)으로 종료되었습니다. 스레드 0x5450이 코드 0 (0x0)으로 종료되었습니다. 스레드 0x5474가 코드 0 (0x0)으로 종료되었습니다.

내가 ASP.NET MVC에서 버그를 발견하지 않은 있으리라 믿고있어 -하지만 난 이해가 안 돼요 어떻게 작업의 내 사용// awaitasync (즉 문제의 가정) ASP.NET의 교착 상태를 만들 수 . 필자는 코드에서 어쨌든 async/await 교착 상태의 전통적인 형식을 배제한 또는 task.Wait()을 호출하며 스레드 스택 추적은 .NET 코드에 없습니다.

+2

질문에 'DoStuff'에 대한 코드를 포함하지 않았으므로 [MCVE] (https://stackoverflow.com/help/mcve)가 없습니다. 또한 왜 예외 처리와 같은 복잡한 프로세스가 필요한지는 명확하지 않습니다. – mason

답변

0

컨트롤러 컨텍스트에서 실행해야하므로 컨트롤러 동작 메서드에서 ConfigureAwait(false)을 호출 할 수 없습니다.