2

System.Net.Httpを使用してネットワークリソースを使用しています。シングルスレッドで実行すると、完全に機能します。TPLを介してコードを実行すると、コードがハングし、タイムアウトになるまで完了しません。

何が起こるかというと、すべてのスレッドがsendTask.Result行で待機することになります。彼らが何を待っているのかはわかりませんが、HttpClientにあるものだと思います。

ネットワークコードは次のとおりです。

using (var request = new HttpRequestMessage(HttpMethod.Get, "http://google.com/"))
{
    using (var client = new HttpClient())
    {
        var sendTask = client.SendAsync
              (request, HttpCompletionOption.ResponseHeadersRead);
        using (var response = sendTask.Result)
        {
            var streamTask = response.Content.ReadAsStreamAsync();
            using (var stream = streamTask.Result)
            {
                // problem occurs in line above
            }
        }
    }
}

私が使用しているTPLコードは次のとおりです。Doメソッドには、上記のコードが正確に含まれています。

var taskEnumerables = Enumerable.Range(0, 100);
var tasks = taskEnumerables.Select
            (x => Task.Factory.StartNew(() => _Do(ref count))).ToArray();
Task.WaitAll(tasks);

いくつかの異なるスケジューラーを試しましたが、それを機能させる唯一の方法は、実行中のタスクの数を2または3に制限するスケジューラーを作成することです。ただし、これでも失敗することがあります。

私の問題はHttpClientにあると思いますが、私の人生の間、コードに共有状態を表示することはできません。誰かアイデアはありますか?

ありがとう、エリック

4

1 に答える 1

2

私はついに問題を見つけました。問題は、HttpClient が独自の追加タスクを発行するため、開始した 1 つのタスクが実際には 5 つ以上のタスクの生成を終了する可能性があることでした。

スケジューラーは、タスク数の制限で構成されました。タスクを開始したため、実行中のタスクの数が上限に達しました。その後、HttpClient は独自のタスクを開始しようとしましたが、制限に達したため、タスクの数が減少するまでブロックされましたが、タスクが完了するのを待っていたため、タスクの数が減少することはありませんでした。こんにちはデッドロックです。

物語の教訓:

  1. タスクはグローバル リソースである可能性があります
  2. 多くの場合、タスク間に明白でない相互依存性があります
  3. スケジューラは扱いにくい
  4. スケジューラーまたはタスク数のいずれかを制御していると想定しないでください

接続数を調整する別の方法を使用することになりました。

エリック

于 2013-04-16T19:20:34.670 に答える