2014-05-15 2 views
1

새로운 비동기 ExecuteReaderAsync은 CancellationToken을 사용합니다. 이전 동기 ExecuteReader을 취소 할 수있는 방법이 있습니까?ExecuteReader와 함께 CancellationToken을 사용할 수 있습니까?

우리의 경우 모든 데이터 작업은 백그라운드 스레드에서 동기식이므로 await은 옵션이 아닙니다. 두 번째 스레드를 시작하고 싶지 않습니다. Task.Run(() => command.ExecuteReaderAsync(token)).Result은 UI 스레드에서 취소 할 수있는 낭비입니다.

+1

당신은 동기 코드를 고수하고 싶습니다. 왜'ExecuteReader (...) '를'ExecuteReaderAsync (token, ...).'로 대체하지 않았습니까? 'Task.Run'으로 랩핑하지 않아도됩니다. – Noseratio

+0

@Noseratio Duh, UI 스레드에서 교착 상태가 발생하는 데 익숙하지만 백그라운드 스레드의 경우 ExecuteReaderAsync (...). 결과가 아름답게 작동합니다. 잠깐, 블록스럽지 않고 스레드 풀 스레드를 사용하여 연속 작업을 처리합니까? 내 확장 메서드는 모든 스레드에서 한 스레드에 머무르는 이점이 있다고 생각합니다. – jnm2

+0

예, ExecuteReaderAsync (...). 결과는 호출 된 스레드를 차단합니다. 그러나 장면 뒤에 비동기 IO를 사용할 수 있으므로 반드시 스레드를 차단하는 것은 아닙니다. (확실하지는 않지만 논리적입니다.) 어쨌든, 당신이 앱의 확장성에 관심이 있다면'async/await'을 사용하고 스레드를 중복해서 차단하지 마십시오. – Noseratio

답변

1

성능 테스트는 스레드 풀 연속으로 Begin 또는 Async API를 사용하는 것과 비교하여 전용 동기 데이터 읽기 스레드 사용시 거의 2 배의 성능 이점을 나타 냈습니다. (행 수천만이 많은 초에서 적재되기 때문에, 우리는이 경우에 성능을 선호합니다.)

연장의 편리한 토큰 전달을위한 방법

public static SqlDataReader ExecuteReader(this SqlCommand command, CommandBehavior commandBehavior, CancellationToken cancel) 
{ 
    try 
    { 
     using (cancel.Register(command.Cancel)) 
      return command.ExecuteReader(commandBehavior); 
    } 
    catch (SqlException) 
    { 
     cancel.ThrowIfCancellationRequested(); 
     throw; 
    } 
} 

내가 리플렉터 컴파일 일부 동굴 탐험을했다. 시작 및 비동기 버전은 모두 매우 절약 적이지만 완전히 TPL 비동기를 기반으로합니다. 그렇기 때문에 둘 다에서 연속에 대한 스레드 풀 디스 패칭이 있습니다.

이 확장 메서드는 스레드 오버 헤드가 없습니다. 토큰 소스에서 Cancel을 호출하는 스레드는 command.Cancel을 호출하여 즉시 데이터 스레드에 SqlException을 발생시킵니다.

0

나는 당신의 편집에 정식으로 응답 할 수 없습니다하지만 당신은 당신의 처음 질문에 대해 알아야 할 몇 가지있다 :

  1. Task.Run(...).Result가 차단은; 그 구문은 약간 오도 된 것입니다.
  2. await Task.Run(() => command.ExecuteReaderAsync(token));은 실행중인 메소드의 나머지 부분 만 차단합니다. 나머지는 콜백으로 처리 할 수 ​​있습니다.
  3. await Task.Run(() => command.ExecuteReaderAsync(token), token);은 위와 같이 작동하지만 작업 병렬 라이브러리가 취소 토큰에도 적용됩니다.

this msdn article은 ExecuteReaderAsync()가 cancelationToken을 실제로 준수하고 있음을 나타냅니다. 프레임 워크에는 실제로 그렇게하지 않을 몇 가지 방법이 있다는 것을 명심하십시오.

+0

예. 'ExecuteReader'가 '.Result'와 마찬가지로 차단됩니다. 동기식'ExecuteReader'는 제가 선호하는 것입니다. 이것은 모두 비동기 연속 스케쥴링을 필요로하지 않는 배경 스레드에 있기 때문에'await'는 문제가되지 않습니다. – jnm2

관련 문제