5

Profile158 (Windows ストア、.NET 4.5、Silverlight 5、Windows Phone 8) をターゲットとするポータブル クラス ライブラリ (PCL) があります。Task 型を返すメソッドを簡単に操作でき、すべて期待どおりに機能します。Result プロパティにアクセスすると、非同期コードの実行が終了し、結果が返されます。

ただし、PCL 内のメソッドで async/await キーワードを使用すると、タスクが返されます。ただし、Result プロパティにアクセスしようとすると、ブロックされて戻りません。

どちらの場合も、Visual Studio のデバッグ出力ウィンドウを見ると、同じテキストが表示されます。

Thread started: 
Thread started: 
Loaded assembly: Mono.Security.dll [External]
Thread started: 
Thread started: 

そのため、コードが実行されているように見えますが、UI スレッドに戻ることはありません。PCL で Microsoft.bcl.async を使用して PCL を使用しようとした人はいますか?

私の Mono Droid プロジェクトは、Android 2.1 を対象としています。

ありがとう、 -- ジョン

更新:
さまざまなシナリオに関する追加情報を次に示します。まず、UI コードで記述した場合に Mono Droid で動作するコードを次に示します。

var task = request.GetResponseAsync();
string html = task.Result.GetResponseText();

次に、PCL で次のメソッドを作成しました。

public async Task<string> Test()
{
    IHttpResponse responce = await GetResponseAsync();
    return responce.GetResponseText();
}

そして、Mono UI コードから次のコードで呼び出します。

string html = request.Test().Result;

それは二度と戻らない…

4

1 に答える 1

3

ブログで説明しているように、これは古典的なデッドロック シナリオです。

デフォルトでawaitは、「コンテキスト」をキャプチャし、それを使用してメソッドを再開しasyncます。この「コンテキスト」は、SynchronizationContextそうでない限り現在のものでありnull、そうでない場合は現在のものTaskSchedulerです。

つまり、async( を提供するSynchronizationContext) UI スレッドからメソッドを呼び出してから、 を呼び出して UI スレッドをブロックしていますResultasyncブロックされている UI スレッドで終了しようとしているため、メソッドを終了できません。

これを修正するには、次のガイドラインに従ってください。

  1. 下まで使用asyncしてください。メソッドから返された に対してResultorWaitを呼び出さないでください。代わりに使用します。Taskasyncawait
  2. ConfigureAwait(false)ライブラリ コードで可能な限り使用してください。

asyncmy / awaitintroも参考になるかもしれません。

于 2013-01-31T17:46:03.317 に答える