2012-04-30 10 views
0

私は.NET 4.5でawaitキーワードを使用することと同じように、.NET 4でTask結果を待つことを試みています。あなたが予想されるように、のGetResponseコールが上で実行されている.NET 4の非ブロックTask.wait?

Private Function GetXDocumentFromWebLocationAsync(ByVal request As WebRequest) As XDocument 
     Dim queryTask As Task(Of WebResponse) 
     queryTask = task(Of WebResponse).Factory.FromAsync(AddressOf request.BeginGetResponse, AddressOf request.EndGetResponse, Nothing, Nothing) 
     Return XDocument.Load(queryTask.Result.GetResponseStream) 
    End Function 

:私はちょうど...しかし、それを行う方法を

私のコード(私は少なくともしようとしていることを証明する)を把握することはできません別のスレッドですが、関数は結果が返されるまで待機する必要があります。残念ながら、これは、タスクが完了するまで私の主なスレッドをブロックし、私はブロックせずにそれを待たせる方法に少しの手がかりを持っていません。非同期CTPを使用したくないのは、それが問題から離れているからです。

秘密のソースとは何ですか?

+0

'Async CTP ...問題から離れているだけです.'私はAsync CTPが問題を"解決 "していると言います。それぞれ自分自身に、私は推測する... –

+0

並べ替えの、しかしCTPは.NET 4.5がもたらすもののプレビューのようなものです。プロダクションコードで使用するものではありません。そして、それはタスクAPI上に構築されているので、無事に行うことができるはずです。 –

+1

まあ、私はかなり長い間、プロダクションコードで使ってきましたが、私も非常に限られたユーザベースしか持っていません。 :) CTPは実際にVS11コンパイラのプレビューです。 VS11 Betaを「.NET 4 async targeting pack」とともに使用して、必要に応じて.NET 4ソリューションを開発することができます。それはタスクをベースにしていますが、正確な重複は[多くの作業です](http://msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx)。 –

答えて

3

秘密のソースはありません。何らかの非同期操作の結果を返すメソッドを作成する場合は、操作が完了するまでスレッドをブロックするだけで済みます。

しかし、同じことを達成する他の方法があります。 .Netでこれを行う "古い"方法は、WebRequestと同じです:BeginGetXDocumentEndGetXDocumentという2つの方法があります。操作が完了したときに実行されるBeginメソッドにデリゲートを渡すことができます。

これを行う別の方法は、Taskをメソッドから戻すことです。それを行うには、ContinueWith()を使用することができます。

Private Function GetXDocumentFromWebLocationAsync(ByVal request As WebRequest) As Task(Of XDocument) 
    Dim queryTask As Task(Of WebResponse) 
    queryTask = Task(Of WebResponse).Factory.FromAsync(
     AddressOf request.BeginGetResponse, AddressOf request.EndGetResponse, Nothing, Nothing) 
    Return queryTask.ContinueWith(
     Function(antecendent) XDocument.Load(antecendent.Result.GetResponseStream)) 
End Function 

この方法で、メソッドの消費者が同期(Wait()またはResultを使用して)結果を待つことを選択することができ、またはそれは再びContinueWith()を使用することができます。

GUIアプリケーションでContinueWith()を使用する場合は、デフォルトでThreadPoolスレッドで継続が実行されるように注意する必要があります。 GUIスレッドで継続を実行するには、TaskScheduler.FromCurrentSynchronizationContext()を使用します。または、あなたのGUIライブラリ(WPFのDispatcher.Invoke()、WinformsのControl.Invoke())固有のメソッドです。

+0

したがって、私が正しく理解すれば、ブロックを避けるためにContinueWith()呼び出しで残りのコードをチェーンすることができますか? –

+0

はい、正確です。しかし、これがあなたのメソッドの戻り値の型を 'X'から' Task(Of X) 'に変更することを忘れないでください。しかし、メソッド全体を通していくつかのことを待つ場合は、 'ContinueWith()'を使用すると、コードをかなり速く読むことができなくなります。それはC#5が待っている場所です。 – svick

+0

私はまだ始まり/終わりのメソッドとイベントハンドラを全部持っているよりも優れていると思います! –