2014-11-03 1 views
5

동기식 메서드의 비동기 래퍼를 만드는 것이 더 좋을까요?비동기 래퍼를 만드는 방법

// sync method 
public void LongOperation() 
{ 
    //code... 
} 


// versions of wrapper 
public async Task LongOpertionWrapperAsyncV1() 
{ 
    var task = Task.Factory.StartNew(LongOperation); 
    await task.ConfigureAwait(false); 
} 

public Task LongOpertionWrapperAsyncV2() 
{ 
    var task = Task.Factory.StartNew(LongOperation); 
    task.ConfigureAwait(false); 
    return task; 
} 

두 버전의 사용은 다르지 않지만. 값 (작업 <T>)을 반환 방법에 대한

async Task Executor() 
{ 
    await LongOpertionWrapperAsyncV1(); 
    await LongOpertionWrapperAsyncV2(); 
} 

, 나는 첫 번째 버전을 사용합니다.

그러나 귀하의 의견을 알고 싶습니다.

그리고 이러한 버전간에 일반적인 차이점이 있습니까?

+2

기록 : http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx – ken2k

+0

BTW, this :'task.ConfigureAwait (false);'는하지 않습니다. *아무것도*. 'ConfigureAwait()'*는 대기 시간을 반환합니다. 반환 값을 무시하면 아무 효과가 없습니다. – svick

답변

4

당신은 V2 "같은"을 사용해야합니다

public Task LongOpertionWrapperAsyncV2() 
{ 
    return Task.Run(LongOperation); 
} 

async Task Executor() 
{ 
    await LongOpertionWrapperAsyncV2().ConfigureAwait(false); 
} 

이 V1에 비해 당신에게 하나의 상황에 스위치를 저장합니다. "다른 작업을 기다리는"필요가없고 async-Task가 메서드의 마지막 작업 인 경우 작업을 기다리는 대신 작업을 반환하고 호출자에게 대기 상태로 남겨 둘 수 있습니다 (이 작업도 추가 할 수 있거나 추가 할 수 없음). ConfigureAwait).

Task.Factory.StartNew은 HPT가 제안한 TaskCreationOptions.LongRunning을 제공하려는 경우에만 필요합니다.

UPDATE : 스티븐로
이미 meantioned : 당신이 async over sync을 (그러나이있다)한다 아주 몇 가지 경우가 있습니다. 이와 같이 구현하기 전에 무엇을하고 있는지 생각해보십시오. 간결한 말했다 : 만약 그것이 "IO를 기다리고"일종의 CPU가 바인딩 된 일을하지 않으면, 그것을 할 수 있습니다.
여기에서는 서로 다른 HW 장치를 제어하는 ​​"거의 비동기식"라이브러리를 개발했습니다.

public async Task<byte[]> ReadAsync(int length) 
{ 
    return Task.Run(() => hwDevice.Read(length)); 
} 

hwDevice.Read은 여전히 ​​수행합니다 우리가 같이 할이 전체 "일반 라이브러리는"비동기이지만, 낮은 수준의 장치 드라이버 및/또는 액세스 라이브러리의 일부는 매우 낮은 수준에 너무 async을 지원하지 않습니다 쓰레드를 잠그지 만 CPU는 잠그지 않아야합니다. 그래서 UI가 IO 동안 기다리고있는 동안 반응합니다 ("실제 라이브"에서는 취소와 오류 처리 로직이 주위에 있습니다).

14

Neither solution is correct. 가장 좋은 대답은 이 아니며은 동기식 코드 용 비동기 메서드를 노출하지 않습니다. 나는 "왜"on my blog에 더 자세히 들어가 있습니다.

코드가 비동기이면 asyncawait을 사용하십시오. 그렇지 않다면하지 마십시오. 발신자가 코드를 호출하는 방법 (예 : Task.Run 사용)은 발신자에게 달려 있어야합니다.

+0

비동기식이어야하는 동기식 메서드를 래핑하는 올바른 방법이 있습니까? 즉동기 메서드 인 GetDatabaseData()가 있다고합시다. DB 호출은 I/O 바운드이기 때문에 비동기로 만들 수있는 방법이 있습니까? – Mackers

+1

@Mackers : 아니요. 메서드가 비동기 적이 지 않으면 구현을 수정하지 않는 한 비동기 메서드를 "만들"수 없습니다. –

+0

@StephenCleary "비동기 차단 금지"게시물을 읽었습니다. 비동기 메서드의 동기 랩퍼를 만들고 싶다면 어떻게해야합니까? 내 동기 메서드 (비동기의 래퍼) 내에서'ConfigureAwait'을 사용해야합니까? – lll

관련 문제