0

는 ... 내가 비동기 방법을Tasks를 기능적으로 유창한 스타일로 동 기적으로 호출하는 방법은 무엇입니까?

public async string MyAsyncMethod() { return await AnyLongRunOperation(); } 

가정 그리고 나는 동기 비동기 메서드 호출하는 일반적인 방법이 : 그런 다음 호출은 다음과 같이 할 수

public static TResult CallSynchronously<TResult>(Func<Task<TResult>> Operation) 
{ 
    var CallingTask = Task.Run(() => Operation()); 
    CallingTask.Wait(); 

    return CallingTask.Result; 
} 

를 (잘 작동하는) : 나는 기능 유창한 스타일로 호출 할 수있는 확장 메서드에서 그 방법을 변환 할 경우

string ResultMessage = CallSynchronously(() => MyAsyncMethod()); 

하지만 (그래서 람다 a를 통과 피하기 위해 의 매개 변수)를 선택한 다음, 나는 ... ...이 함께

var Result = MyAsyncMethod().CallSynchronously(); 

public static TResult CallSynchronously<TResult>(this Task<TResult> Operation) 
{ 
    var CallingTask = Task.Run(() => Operation.Result); 
    CallingTask.Wait(); 

    return CallingTask.Result; 
} 

그래서 지금처럼 호출 할 수 있습니다를 tryed 그러나 문제는 여기에있다 : 그것은 달려!

그래서 질문입니다. 기능성 유창한 스타일로 작업을 동 기적으로 호출하는 방법은 무엇입니까?

답변

1

프랭크가 언급했듯이, 당신은 아마도 내가 describe in full on my blog 인 교착 상태를 보게 될 것입니다. 이 코드 블록 사이의 차이 :

string ResultMessage = CallSynchronously(() => MyAsyncMethod()); 

과 :

var Result = MyAsyncMethod().CallSynchronously(); 

MyAsyncMethod가 호출되는 상황이다. 첫 번째에서는 스레드 풀 컨텍스트 (Task.Run 내)에서 호출됩니다. 두 번째 것은 직접 호출됩니다. 아마도 이것은 UI 스레드에서 발생하기 때문에 이 MyAsyncMethod에 있으면 UI 컨텍스트를 캡처하여 해당 컨텍스트에서 메서드를 다시 시작하려고 시도합니다. 한편 CallSynchronously은 UI 스레드를 차단하여 교착 상태를 일으 킵니다.

진짜 문제는 여기에 있습니다 :

내가 비동기 메서드를 호출하는 일반적인 방법을 동 기적으로

매우 드문 상황 거기, BTW (동기 비동기 메소드를 호출 받아 들일 경우가 있습니다 아니요 사용 사례 UI 수행자에서 을 수행하는 것으로 생각하면됩니다. 확실히 시나리오가되어서는 안됩니다. 확실히은 그 목적을 위해 유틸리티 메소드를 가질만큼 충분하지 않아야합니다. 이 방법의 존재는 응용 프로그램의 설계에 심각한 오류가 있음을 나타냅니다.

var Result = await MyAsyncMethod(); 
+0

내가 당신에게 사건을 줄 것이다 : 당신은 다른 웹 서비스에 의존하는 중간 웹 서비스, 계산해야하는 대신 함께 동기 대비 비동기 코드를 해킹 시도의

, 단지 비동기 포옹 결과. 비동기가 항상 가능하지는 않습니다. –

+0

설명을 주셔서 감사합니다. 그러나 질문은 '왜'정지하지 않고 매달리지 않고 유창하게 (기능적 스타일) '부르는 법'입니다. –

+1

@ NéstorSanchezA : 귀하의 경우에는 중간 웹 서비스를 비동기로 설정하십시오. 처음으로 포장하지 않으면 유창한 방법이 없습니다 (예 :'Fluent (MyAsyncMethod) .CallSynchronously()'). –