以下のサンプルでは、非同期の "Process"関数が同期的に呼び出されたときに、 "await Task.Delay(1000)"への呼び出しによってUIがハングアップするのがわかります。
"await Task.Delay(1000).ConfigureAwait(false)"を呼び出すか、 "Process"呼び出しを別のタスク内にラップすることでハングを回避できることがわかりました。私は、問題がsynchornizationcontextにあることを理解できます、そして、私が呼び出しを "Task.Delay(1000).Wait()"という呼び出しに置き換えるならば、awaitはそれと幻想的な何かをしているのを知っています。ハングしません。
誰かがその動作を説明してもらえますか(私はildasmコードを見てみましたが、役に立ちませんでした)。どうもありがとう。
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
public async void OnLoaded(object sender, RoutedEventArgs args)
{
var task = Process();
MessageBox.Show(task.Result);
}
public async Task<String> Process()
{
await Task.Delay(1000);
return "";
}
まず、メソッドは常に同期的に呼び出されます。いつOnLoaded
が呼び出されると、Process
方法。
のProcess
メソッドを呼び出すTask.Delay
メソッドへの参照を取得します。Task<string>
待っている物。これは、後のコードがawait
後で実行され、Process
メソッドはこの時点で戻ります。
のOnLoaded
メソッドはへの参照を取り戻しますTask<string>
格納するオブジェクトtask
変数。それからResult
タスクを取得します。これは、タスクが完了するまで現在のスレッドをブロックします。
1秒後、Process
メソッドの試行は続行されます。 UIスレッドでタスクを開始したので、スケジューラはProcess
UIスレッドのメソッドしかし、UIスレッドはResult
ゲッターコールreturn "";
文は実行されません。
task.Result
「タスクが完了するまでUIをハングアップしてから結果を使用する」という意味です。await task
「発呼者に制御を譲渡する」という意味。タスクが完了したら、タスクの継続を将来の都合の良いときに実行するようにスケジュールし、その結果を使用します" - Eric Lippert