어떤 접근 방법이 일반적으로 메모리 및 리소스 사용면에서 더 효율적인지 궁금합니다.작업을 사용하여 비동기 기능 다시 시도 - 어떤 접근 방식이 더 효율적입니까?
접근 방식 # 1을 사용하면 작업 객체가 어떻게 생성되고 스레드가 회전되는지 시각화하는 데 어려움을 겪고 있습니까? 누군가 제발 제쳐두고 세부적으로 덮개 밑에서 어떻게되는지 설명해 주시겠습니까?
둘 사이에 차이가 없다면 # 1을 사용하고 싶습니다. (비동기가 발생하지 않도록하고 싶습니다.) # 2를 사용하면 컴파일러가 상태 머신을 생성하고 리턴 할 것이라는 것을 이해합니다. OTOH, # 1은 재귀 적으로 개념적으로 보이지만 다른 스택에서 대기하는 한 스택 프레임처럼 전통적인 의미에서 재귀적일 것인가?
접근법 # 1 :
internal static Task ExecuteAsyncWithRetry(Func<Task> methodToExecute, Func<bool> shouldRetry)
{
var tcs = new TaskCompletionSource<object>();
try
{
return methodToExecute().ContinueWith<Task>((t) =>
{
if (t.IsFaulted || t.IsCanceled)
{
if (shouldRetry())
{
return ExecuteAsyncWithRetry(methodToExecute, shouldRetry);
}
else
{
tcs.SetException(t.Exception);
}
}
else
{
tcs.SetResult(null);
}
return tcs.Task;
}, TaskContinuationOptions.ExecuteSynchronously).Unwrap();
}
catch(Exception ex)
{
tcs.SetException(ex);
}
return tcs.Task;
}
접근법 # 2 (둘 사이 예외 전파의 차이를 무시하는) 다른 예외 취소 전파 게다가
internal static async Task ExecuteWithRetry(Func<Task> methodToExecute, Func<bool> shouldRetry)
{
while (true)
{
try
{
await methodToExecute();
}
catch(Exception ex)
{
if(!shouldRetry())
{
throw;
}
}
}
}
두 번째 방법은 읽고 이해하는 것이 더 명확합니다. 내 경험에 비추어 볼 때 가능한 한 비동기 적으로 기다려야합니다. 그리고 당신의 경우에 가능합니다. 하지만 두 번째 경우에 어떤 종류의 종료 조건이 누락되었습니다. 모든 것이 잘되면'methodToExecute()' 이 반복해서 실행됩니다. – Krumelur
AggregateException을 처리하지 않기 때문에 오류 정보가 손실됩니다. 이 같은 일반적인 도우미 메서드에 바람직하지 않습니다. 예외를 해석하는 일은 아닙니다. – usr
감사합니다. 그러나, 오류 정보 부분을 잃어 버리셨습니까? UnWrap()과 같은 동작을 기다리지 말고 내부 작업의 오류/예외를 전파해야합니까? – Kakira