私は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
。
それは効率的に実施されたカスタムウェイターとして。同じ効果を生み出す効率の悪いコードは、これと同じくらい単純かもしれません。
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
w /適切なタスクスケジューラ
また見なさい:
Task.Yield()
非同期メソッドのモック実装で使用されるかもしれません。
await Task.Yield()
メソッドを非同期にするように強制します。なぜ、" real"と書くのが面倒になるのでしょうか。非同期コード?重い同期方法を想像してください。非同期にするには、単に追加するだけです。async
そしてawait Task.Yield()
初めに魔法のように、それは非同期になりますか?これは、ほとんどすべての同期コードを次のコードにラップするようなものです。Task.Run()
そして偽の非同期メソッドを作成します。 - KrumelurTask.Run
実装するExecuteFooOnUIThread
UIスレッドではなく、スレッドプールで実行されます。ありawait Task.Yield()
つまり、後続のコードが現在のコンテキストで実行されるように(後の時点で)非同期にするよう強制します。それはあなたが通常することではありませんが、それが何らかの奇妙な理由で必要とされるならオプションがあるのはうれしいです。 - Reed CopseyExecuteFooOnUIThread()
非常に長い間実行されていました、それはまだある時点で長い間UIスレッドをブロックして、UIを無反応にするでしょう、それは正しいですか? - Krumelur