1

HTTP 要求を送信するためにプラットフォーム固有の API にアクセスする必要があるポータブル クラス ライブラリで作成された API があります。WinRT で HTTP POST を実行するために私が書いたメソッドを次に示します。

   public bool Post(IEnumerable<KeyValuePair<string, string>> headers, string data)
    {
        bool success = false;
        HttpClient client = new HttpClient(new HttpClientHandler {AllowAutoRedirect = false});
        foreach (var header in headers)
        {
            client.DefaultRequestHeaders.Add(header.Key, header.Value);
        }

        try
        {
            var task=client.PostAsync(endpoint, new StringContent(data, Encoding.UTF8, "text/xml")).ContinueWith( postTask =>
                    {
                        try
                        {
                            postTask.Wait(client.Timeout); //Don't wait longer than the client timeout.
                            success = postTask.Result.IsSuccessStatusCode;
                        }catch {}
                    }, TaskContinuationOptions.LongRunning);
            task.ConfigureAwait(false);
            task.Wait(client.Timeout);

        }
        catch
        {
            success = false;
        }

        return success;
    }

ただし、これは、何らかのストレス下に置かれた場合に興味深い問題を示します。内部でデッドロックしているようです。5 つのスレッドを作成し、それらから POST リクエストを送信した場合と同様に、このメソッドはタイムアウト以外の処理を行わない場所に到達します。コンテンツがサーバーに到達することはなく、.Continueコードが実行されることもありません。ただし、シリアルで実行したり、2 つまたは 3 つのスレッドで実行したりすると、問題なく動作します。スローされるスレッドが増えるほど、パフォーマンスが指数関数的に悪化するようです

ここで何が間違っているのですか?

4

3 に答える 3

2

これがあなたの問題だとは思いませんが、そうなる可能性があり、実装してテストするのは本当に簡単です。デフォルトでは、Windows は最大ネットワーク接続数を 2 に設定し、2 つを超えるスレッドを使用すると、接続プールでロックされる可能性があります。これをアプリ構成に追加できます

<system.net>
  <connectionManagement>
    <add address="*" maxconnection="300" />
   </connectionManagement>
</system.net>

またはコードでこれを行うことができます

ServicePointManager.DefaultConnectionLimit = 300

また、続行中の待機をコメントアウトすることも検討します。必要ないと思います。

try
{
    //Comment this line out your handling it in the outside task already
    //postTask.Wait(client.Timeout); //Don't wait longer than the client timeout.
    success = postTask.Result.IsSuccessStatusCode;
 }catch {}

最後に、上記の 2 つのことがうまくいかない場合は、このコードをコメントアウトしてみます。

//Task.ConfigureAwait(false);

Task.Wait と設定 Task.ConfigureAwait(false) の組み合わせが何らかのデッドロックを引き起こしている可能性がありますが、私はその理由について専門家ではありません。マルチスレッドで問題なく実行される非常によく似たコードがいくつかあり、コードに Task.ConfigureAwait(false) がないことを知っているだけです。主に HttpClient ライブラリを試してみましたが、.NET 4.5 にアップグレードしなかったためです。そのため、 await は利用できません。

于 2013-04-17T20:19:15.133 に答える