1

皆さん、私は奇妙な状況に陥っています。返されるさまざまなタイプのタスクを一緒にチェーンする必要があります。通常、このようなことができます

Task<T> t = Task<T>.Factory.StartNew(() => ... some T instance);
Task t2 = t.ContinueWith<U>(parent => ...);
return Task.WhenAll(t, t2);

ただし、私の複雑な点は、FromAsyncヘルパー メソッドを使用して Begin/End ペアをラップし、それを Task に変換することにあります。.NET 4.0 で HttpWebRequest とタスクを使用して非同期クライアントを作成しようとしています (したがって、await はオプションではありません)。

私の問題は、戻り値の型がFromAsyncTask 自体であるため、ContinueWithメソッドでそれを使用できないことです (ContinueWith戻り値の型を期待し、データ自体をTaskオブジェクトにラップします)。

これは私がこれまでに持っていたコードで、正しい機能的な結果をもたらしますが、真に非同期ではありません:

public Task<string> GetHttpRequest(string url, string contentType)
{
    var httpWebRequest = CreateHttpWebRequest(url, "GET", contentType);
    Task<WebResponse> httpTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null);

    return httpTask.ContinueWith(httpAntecedent =>
          {
              WebResponse webResponse = httpAntecedent.Result;
              Stream responseStream = webResponse.GetResponseStream();
              byte[] data = new byte[webResponse.ContentLength];

              var streamReadTask = Task<int>.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, data, 0, data.Length, TaskCreationOptions.AttachedToParent);

              return streamReadTask.ContinueWith(parent =>
                  {
                      responseStream.Close();
                      webResponse.Close();

                      return Encoding.UTF8.GetString(data);
                  });
          }).Result;
}
4

1 に答える 1

3

質問を言い換えると、 が完了するのを同期的に待つことなく、そこTask<Task<string>>から取得したいと考えています。Task<string>Task

awaitC# 5.0 では、 double :を使用してこれを行うことができましたreturn await await task;

C# 5.0 がなくても、 を使用できUnwrap()ますreturn task.Unwrap();

何らかの理由でこれを自分でやりたい場合は、ContinueWith()insideContinueWith()と一緒に使用できますTaskCompletionSource


しかし、あなたのコードには欠陥があります。1 回の読み取りで応答全体を取得することを前提としています。これはまったく保証されておらず、実際には正しく機能しないことがよくあります。これを適切に行うには、より複雑なコードが必要になり、おそらくTaskCompletionSource.

于 2013-01-21T13:55:10.333 に答える