IT story

언제 Task.Yield ()를 사용합니까?

hot-time 2020. 5. 12. 08:02
반응형

언제 Task.Yield ()를 사용합니까?


나는 async / await을 Task많이 사용 Task.Yield()하고 있지만 왜이 방법이 필요한지 이해할 수없는 모든 설명으로도 사용 하고 정직하지 않았습니다.

누군가 Yield()가 필요한 곳에서 좋은 모범을 보일 수 있습니까 ?


async/ 를 사용할 때 await호출 할 때 호출하는 메소드 await FooAsync()가 실제로 비동기 적으로 실행 된다는 보장은 없습니다 . 내부 구현은 완전히 동기화 된 경로를 사용하여 자유롭게 반환 할 수 있습니다.

차단하지 않고 일부 코드를 비동기식으로 실행하는 것이 중요한 API를 작성하는 경우 호출 된 메소드가 동 기적으로 (효과적으로 차단) 실행될 가능성이있는 경우를 사용 await Task.Yield()하면 메소드가 비동기식으로 돌아가고 그 시점에서 제어합니다. 나머지 코드는 현재 컨텍스트에서 나중에 실행됩니다 (이 시점에서 여전히 동 기적으로 실행될 수 있음).

이것은 "장기 실행"초기화가 필요한 비동기 메소드를 만드는 경우에도 유용합니다.

 private async void button_Click(object sender, EventArgs e)
 {
      await Task.Yield(); // Make us async right away

      var data = ExecuteFooOnUIThread(); // This will run on the UI thread at some point later

      await UseDataAsync(data);
 }

Task.Yield()호출 하지 않으면 메소드는 첫 번째 호출까지 동기식으로 실행됩니다 await.


내부적 await Task.Yield()으로는 현재 동기화 컨텍스트 또는 무작위 풀 스레드 (있는 경우 SynchronizationContext.Current) 에서 연속을 대기열에 넣습니다 null.

그것은되어 효율적으로 구현 사용자 정의 awaiter한다. 동일한 효과를 생성하는 덜 효율적인 코드는 다음과 같이 간단 할 수 있습니다.

var tcs = new TaskCompletionSource<bool>();
var sc = SynchronizationContext.Current;
if (sc != null)
    sc.Post(_ => tcs.SetResult(true), null);
else
    ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(true));
await tcs.Task;

Task.Yield()이상한 실행 흐름 변경에 대한 바로 가기로 사용할 수 있습니다. 예를 들면 다음과 같습니다.

async Task DoDialogAsync()
{
    var dialog = new Form();

    Func<Task> showAsync = async () => 
    {
        await Task.Yield();
        dialog.ShowDialog();
    }

    var dialogTask = showAsync();
    await Task.Yield();

    // now we're on the dialog's nested message loop started by dialog.ShowDialog 
    MessageBox.Show("The dialog is visible, click OK to close");
    dialog.Close();

    await dialogTask;
    // we're back to the main message loop  
}

즉, 적절한 작업 스케줄러 Task.Yield()로 교체 할 수없는 경우는 생각할 수 없습니다 Task.Factory.StartNew.

또한보십시오:


Task.Yield()비동기 재귀를 수행 할 때 스택 오버플로를 방지하는 것이 한 가지 용도입니다 . Task.Yield()동기 연속을 방지합니다.

private static void Main()
    {
        RecursiveMethod().Wait();
    }

    private static async Task RecursiveMethod()
    {
        await Task.Delay(1);
        //await Task.Yield(); // Uncomment this line to prevent stackoverlfow.
        await RecursiveMethod();
    }

Task.Yield() 비동기 메소드의 모의 구현에 사용될 수 있습니다.

참고 URL : https://stackoverflow.com/questions/22645024/when-would-i-use-task-yield

반응형