2014-03-24 2 views
0

현재 Task.Run을 사용해야 할 시점과 그렇지 않은 경우를 파악하려고합니다.Asp.Net WebApi를 실행하여 MongoDB 쿼리/비동기 저장

내 프로젝트에서 계정 정보를 저장하기 위해 MongoDB와 결합 된 WebApi를 사용하고 있습니다.

다음 샘플 코드에서는 클라이언트 호출에서 Submit 또는 SumbitAsync 메서드를 사용하는 것이 더 좋을까요?

public class TestController : ApiController 
{ 
    [HttpPost] 
    public void Submit() 
    { 
     DoSave(); 
    } 

    public async Task SubmitAsync() 
    { 
     await Task.Run(() => DoSave()); 
    } 

    private void DoSave() 
    { 
     myMongoDbCollection.Save(new TestEntity()); 
    } 
} 

MongoDB C# 드라이버는 현재 비동기 메서드를 지원하지 않습니다.

답변

1

여기서 Task.Run을 사용하는 것은 의미가 없습니다.

ASP.NET에서 비동기 I/O를 사용하면 스레드를 비우는 것이므로 I/O가 완료 될 때까지 다른 요청을 처리 할 수 ​​있습니다. 한편, 스레드가 차단됩니다. I/O 작업이 완료되면 I/O 완료 포트가 신호를 받고 메서드가 다시 시작됩니다.

Task.Run을 사용하면 이것을 ThreadPool 스레드로 지연시키고 스레드 블록이 I/O를 기다리는 중입니다.

즉, 클라이언트가 비동기 I/O를 지원하지 않으면 스레드 중 하나가 항상 차단됩니다. 따라서 동기식으로 모든 작업을 수행하고 불필요한 컨텍스트 전환을 피할 수 있습니다. Stephen Cleary's blog post "Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation"에서

:

있습니다 즉시 사용 ASP.NET에서 Task.Run으로 기다리고 도입 네 효율성 문제 (적어도) :

  • 추가 (불필요) 스레드 Task.Run 스레드 풀 스레드로 전환합니다. 마찬가지로, 해당 스레드가 요청을 완료하면 요청 컨텍스트 (실제 스레드 스위치가 아니지만 오버 헤드가 있음)를 입력해야합니다.

  • 여분의 (불필요한) 쓰레기가 생성됩니다. 비동기 프로그래밍은 단점입니다. 메모리 사용량이 많아지면 응답 속도가 빨라집니다. 이 경우 완전히 필요하지 않은 비동기 작업을 위해 더 많은 가비지가 생성됩니다.

  • ASP.NET 스레드 풀 휴리스틱은 Task.Run에 의해 예기치 않게 스레드 풀 스레드를 빌려서 제거됩니다. 여기서 많은 경험이 없지만 예기치 않은 작업이 실제로 짧다면 예상치 못한 작업이 2 초 이상 지속될 경우 휴리스틱 스가 훌륭하게 회복되어야하며 우아하게 처리하지 못할 것이라고 내 직감이 말해줍니다.

  • ASP.NET은 요청을 일찍 종료 할 수 없습니다. 즉, 클라이언트의 연결이 끊어 지거나 요청 시간이 초과됩니다. 동기식의 경우 ASP.NET은 요청 스레드를 알고 있었으며 중단시킬 수있었습니다. 비동기의 경우 ASP.NET은 보조 스레드 풀 스레드가 해당 요청에 "대한"것인지 인식하지 못합니다. 취소 토큰을 사용하여 문제를 해결할 수도 있지만이 블로그 게시물의 범위를 벗어납니다.

관련 문제