2

以下のサンプルでは、非同期の "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 "";
}


  • 要するに:task.Result「タスクが完了するまでUIをハングアップしてから結果を使用する」という意味です。await task「発呼者に制御を譲渡する」という意味。タスクが完了したら、タスクの継続を将来の都合の良いときに実行するようにスケジュールし、その結果を使用します" - Eric Lippert

1 답변


3

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

Processメソッドを呼び出すTask.Delayメソッドへの参照を取得します。Task<string>待っている物。これは、後のコードがawait後で実行され、Processメソッドはこの時点で戻ります。

OnLoadedメソッドはへの参照を取り戻しますTask<string>格納するオブジェクトtask変数。それからResultタスクを取得します。これは、タスクが完了するまで現在のスレッドをブロックします。

1秒後、Processメソッドの試行は続行されます。 UIスレッドでタスクを開始したので、スケジューラはProcessUIスレッドのメソッドしかし、UIスレッドはResultゲッターコールreturn "";文は実行されません。


  • 申し訳ありませんが、そうではありません。UIがハングして""を返します。呼び出されることすらありません(ブレークポイントを設定して自分で見てください)。 - Rohit Sharma
  • ありがとう、どうしてクリックしないのかわからない。 :) - Rohit Sharma
  • +1。このデッドロックについてさらに詳しく説明します。私のブログでそしてMSDNの記事私のブログ投稿には、いくつかのデッドロックデモを含む詳細情報へのリンクがあります。 - Stephen Cleary

関連する質問

最近の質問