[C#] void async 메소드 대기

void async메소드가 작업을 완료하기를 기다리는 방법은 무엇입니까?

예를 들어 다음과 같은 기능이 있습니다.

async void LoadBlahBlah()
{
    await blah();
    ...
}

이제 다른 곳에서 계속하기 전에 모든 것이로드되었는지 확인하고 싶습니다.



답변

가장 좋은 방법은 기능이 async void불인 경우에만 기능을 표시 하고 방법을 잊어 버리고 기다리는 경우에는로 표시해야합니다 async Task.

만약 당신이 여전히 기다리고 싶다면, 그렇게 포장하십시오 await Task.Run(() => blah())


답변

함수의 서명을로 변경할 수 있다면 여기에async Task 제시된 코드를 사용할 수 있습니다


답변

가장 좋은 해결책은를 사용하는 것 async Task입니다. async void몇 가지 이유 때문에 작곡가 는 피해야 합니다.

메소드 가 리턴 될 수없는 경우 Task(예 : 이벤트 핸들러 인 경우) SemaphoreSlim종료하려고 할 때 메소드 신호를 갖는 데 사용할 수 있습니다 . 이것을 finally블록 으로하는 것을 고려하십시오 .


답변

AutoResetEvent를 수행하고 함수를 호출 한 다음 AutoResetEvent를 기다린 다음 완료되었음을 알면 async void 안에 설정하십시오.

당신은 또한 당신의 공허 비동기에서 반환 작업을 기다릴 수 있습니다


답변

실제로 수동으로 아무것도 할 필요가 없으며 await키워드 blah()는 반환 될 때까지 함수 실행을 일시 중지 합니다.

private async void SomeFunction()
{
     var x = await LoadBlahBlah(); <- Function is not paused
     //rest of the code get's executed even if LoadBlahBlah() is still executing
}

private async Task<T> LoadBlahBlah()
{
     await DoStuff();  <- function is paused
     await DoMoreStuff();
}

T객체 blah()반환 유형

당신은 정말 할 수 기능은 그렇게 할 수 없다awaitvoidLoadBlahBlah()void


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 이것은 여전히 ​​겪고있는 문제이지만 여전히 비동기 무효 서명 방법에서 async / await를 사용할 때이를 올바르게 수행하는 명확한 해결책은 없습니다.

그러나 void 메서드 내에서 .Wait ()이 제대로 작동한다는 것을 알았습니다.

async void와 void는 동일한 서명을 가지므로 다음을 수행해야 할 수도 있습니다.

void LoadBlahBlah()
{
    blah().Wait(); //this blocks
}

혼란스럽게도 충분한 비동기 / 대기는 다음 코드에서 차단되지 않습니다.

async void LoadBlahBlah()
{
    await blah(); //this does not block
}

코드를 디 컴파일 할 때 async void는 내부 작업 (비동기 작업과 동일)을 생성하지만 서명은 내부 작업을 반환하도록 지원하지 않기 때문에

이것은 내부적으로 비동기 void 메소드가 내부적으로 비동기 메소드를 “대기”할 수 있음을 의미합니다. 내부 작업이 언제 완료되는지 외부에서 알 수 없습니다.

따라서 제 결론은 비동기 void가 의도 한대로 작동하고 내부 작업의 피드백이 필요한 경우 대신 비동기 작업 서명을 사용해야한다는 것입니다.

잘만되면 나의 학대는 답을 찾는 사람에게도 의미가있다.

편집 : 나는 예제 코드를 만들고 실제로 무슨 일이 일어나고 있는지 확인하기 위해 디 컴파일했다.

static async void Test()
{
    await Task.Delay(5000);
}

static async Task TestAsync()
{
    await Task.Delay(5000);
}

로 바뀝니다 (편집 : 본문 코드는 여기가 아니라 상태 머신에 있지만 상태 머신은 기본적으로 동일하므로 추가하지 않아도됩니다)

private static void Test()
{
    <Test>d__1 stateMachine = new <Test>d__1();
    stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
    <TestAsync>d__2 stateMachine = new <TestAsync>d__2();
    stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
    return stateMachine.<>t__builder.Task;
}

AsyncVoidMethodBuilder 또는 AsyncTaskMethodBuilder는 실제로 Start 메서드에 차단할 힌트를주는 코드가 없으며 시작된 후에는 항상 비동기 적으로 실행됩니다.

반환 작업이 없으면 의미가 완료되었는지 확인할 방법이 없습니다.

예상대로 비동기 실행 작업 만 시작한 다음 코드에서 계속됩니다. 비동기 작업은 먼저 작업을 시작한 다음 반환합니다.

그래서 내 대답은 비동기 void를 절대 사용하지 않는 것 같습니다. 작업이 언제 완료되는지 알아야 할 경우 비동기 작업의 목적입니다.


답변