2016-05-22 17 views
3

async/awaitを理解しようとすると、ボタンが1つのみのサンプルWPFアプリケーションを少し作成しました。クリックされたとき、それはいくつかの仕事」を行います。期待されるスレッドでAsync-Awaitが実行されない

private async void goButtonClicked(object sender, EventArgs e) 
     { 

      WhatThreadAmI(); 
      var task = populateRawData().ConfigureAwait(false); 
      WhatThreadAmI(); 
      BusyIndicator.IsBusy = true;  

      await task; 
      WhatThreadAmI(); //this isnt on the main thread - why?? 
      BusyIndicator.IsBusy = false; 

      Console.WriteLine("fin"); 
     } 

「WhatThreadAmIは」単に私が初期化時にセーブUIスレッドに現在のスレッドを比較します。

public bool IsMainThread => uiThread == Thread.CurrentThread; 

私はこれの出力が真であることが予想 - falseを返すように移入生データ方式では確かに、「WhatThreadAmI」コールで - 真。 。私はここに非常に根本的な何かが欠けする必要があります知っている真

返す移入生データ方式では、「」WhatThreadAmI」コールで、Falseを、誰かが助けてくださいすることができます - 真 - 実際に何が起こる

はTrueです私はない仕上げ作業を待って、一つのスレッドがコードの実行を開始する。

+0

[asyncはスレッドに関するものではありません](http://stackoverflow.com/q/17661428/11683)。 – GSerg

+3

タスクを作成するときに、それが「.ConfigureAwait(false)」と表示されます。つまり、「元のコンテキストで再開する必要はありません。あなたがその仕事を待つとすぐに、あなたの文脈は変わるので、ここでは驚きはありません。単にタスクを作成してもまだそれを待たずにコンテキストを変更しないので、最初の2つの 'WhatThreadAmI'が' true'を返します。 – GSerg

+0

は意味があります - ありがとう! – smodle

答えて

0

Taskオブジェクトは、.NETスレッドプールの上に抽象化しているのですか?何が起こっているかを理解し、別のスレッドから再開すること。

このようにして、ブロックせずにCPUの使用を最大限にすることができます。 oタスクの意味。使用可能なスレッドは、待機が終了するとタスクの実行を続行します。それは過去にタスクを実行したスレッドかもしれませんが、そうでないかもしれません。

+1

私はこの答えが好きです。なぜなら、質問に暗示された批判的な詳細の中心にあるからです。特定のスレッドで特定の動作に頼っている場合、Async Awaitはあなたの解決策ではありません。私はAsync Awaitを「可能であれば並列化してみてください」と表現します。スレッドを「ランダムに」使用してください。あなたがそれを理解しようとしているなら、自明ではない設計とアーキテクチャの詳細がここにあります。あなたが理解しようとするならば、元の質問は良い質問です。なぜそれがすべての環境で期待通りでないのかということは、元の質問が表面にもたらされた素晴らしい例です。 –

+0

拡張していただきありがとうございます。私はAsync/Awaitの機能を根本的に誤解しており、この回答は最初の質問に対処しています。 – smodle

-1

変更ConfigureAwait(false); ConfigureAwait(true)に設定します。または単にそれを削除します。

4
var task = populateRawData().ConfigureAwait(false); 

ConfigureAwait(false)が捕捉コンテキストに再開しないawaiter構成タスクを返します。私はhow await captures and resumes on contextを私のブログに詳しく説明しています。 ConfigureAwait(false)の使用は、ではなく、のコンテキストでのキャプチャとレジュームを意味します。この場合、「コンテキスト」はUIスレッドです。したがって、awaitは、ConfigureAwait(false)が明示的にawaitに必要でないことを伝えているため、UIスレッドの再開は行いません。

このコードのtask変数は、ではありません。には、Taskが含まれています。変数ではなく、ConfigureAwaitの結果を持つことは非常に珍しいことです。次の例では、等価であると - 私は思う - 何が起こっているのかをより明確に表現する:

WhatThreadAmI(); 
var task = populateRawData(); 
WhatThreadAmI(); 
BusyIndicator.IsBusy = true;  

await task.ConfigureAwait(false); 
WhatThreadAmI(); //this isnt on the main thread - why?? 
BusyIndicator.IsBusy = false; 

別の言い方をすれば:それはConfigureAwait、ないConfigureTaskです。タスクをまったく変更するものではありません。 ConfigureAwaitawaitと併用すると意味があります。

関連する問題