When would I use Task.Yield()?

前端 未结 4 1716
走了就别回头了
走了就别回头了 2020-11-29 15:09

I\'m using async/await and Task a lot but have never been using Task.Yield() and to be honest even with all the explanations I do not understand wh

4条回答
  •  猫巷女王i
    2020-11-29 15:24

    Internally, await Task.Yield() simply queues the continuation on either the current synchronization context or on a random pool thread, if SynchronizationContext.Current is null.

    It is efficiently implemented as custom awaiter. A less efficient code producing the identical effect might be as simple as this:

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

    Task.Yield() can be used as a short-cut for some weird execution flow alterations. For example:

    async Task DoDialogAsync()
    {
        var dialog = new Form();
    
        Func 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  
    }
    

    That said, I can't think of any case where Task.Yield() cannot be replaced with Task.Factory.StartNew w/ proper task scheduler.

    See also:

    • "await Task.Yield()" and its alternatives

    • Task.Yield - real usages?

提交回复
热议问题