void async
메소드가 작업을 완료하기를 기다리는 방법은 무엇입니까?
예를 들어 다음과 같은 기능이 있습니다.
async void LoadBlahBlah()
{
await blah();
...
}
이제 다른 곳에서 계속하기 전에 모든 것이로드되었는지 확인하고 싶습니다.
답변
가장 좋은 방법은 기능이 async void
불인 경우에만 기능을 표시 하고 방법을 잊어 버리고 기다리는 경우에는로 표시해야합니다 async Task
.
만약 당신이 여전히 기다리고 싶다면, 그렇게 포장하십시오 await Task.Run(() => blah())
답변
답변
가장 좋은 해결책은를 사용하는 것 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()
반환 유형
당신은 정말 할 수 기능은 그렇게 할 수 없다await
void
LoadBlahBlah()
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를 절대 사용하지 않는 것 같습니다. 작업이 언제 완료되는지 알아야 할 경우 비동기 작업의 목적입니다.