2

以下のサンプルでは、​​非同期の "Process" 関数が同期的に呼び出されると、"await Task.Delay(1000)" の呼び出しによって UI がハングすることがわかります。

「await Task.Delay(1000).ConfigureAwait(false)」を呼び出すか、「Process」呼び出しを別のタスク内にラップすることで、ハングを回避できることがわかっています。問題が同期化コンテキストにあることは理解できます。また、await がそれに何か凝った処理を行っていることもわかっています。たとえば、"await Task.Delay(1000)" 呼び出しを "Task.Delay(1000).Wait()" UI に置き換えると、ハングしません。

誰かが動作を説明してもらえますか (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 "";
}
4

1 に答える 1

3

まず、メソッドは常に同期的に呼び出されます。がOnLoaded呼び出されると、Processメソッドが呼び出されます。

メソッドはメソッドをProcess呼び出し、待機しているオブジェクトTask.Delayへの参照を取得します。Task<string>これは、 の後のコードawaitが後で実行され、Processメソッドがこの時点で戻ることを意味します。

このOnLoadedメソッドは、変数Task<string>に格納されているオブジェクト への参照を取得します。次に、タスクでゲッターをtask呼び出します。Resultこれにより、タスクが完了するまで現在のスレッドがブロックされます。

1 秒後、Processメソッドは続行を試みます。ProcessUI スレッドでタスクを開始したため、スケジューラは UI スレッドでメソッドをスケジュールしようとします。しかし、UI スレッドはResultgetter 呼び出しによってブロックされるため、return "";ステートメントは実行されません。

于 2013-07-06T12:12:42.783 に答える