web-dev-qa-db-ja.com

HttpWebRequest:リクエストは中止されました:リクエストはキャンセルされました

私は、一連の日付(通常は一度に7つ)のHTTPポスト要求を使用してテキストをCMSバックエンドにアップロードする、ある種の中間者アプリケーションの開発に取り組んでいます。これを実現するためにHttpWebRequestを使用しています。最初の日付では問題なく動作するようですが、2番目の日付が始まると、System.Net.WebExceptionが発生します。要求は中止されました。要求はキャンセルされました。

私は周りを検索して、次の大きな手がかりを見つけました:

http://social.msdn.Microsoft.com/Forums/en-US/netfxnetcom/thread/0d0afe40-c62a-4089-9d8b-fb4d206434dc

http://www.jaxidian.org/update/2007/05/05/8

http://arnosoftwaredev.blogspot.com/2006/09/net-20-httpwebrequestkeepalive-and.html

そして、それらはあまり役に立ちませんでした。 GetWebReuqestをオーバーロードしてみましたが、その関数を使用していないので意味がありません。

これが私のコードです: http://Pastebin.org/115268

少なくとも1回は正常に実行された後、245行目にエラーが表示されます。

これは私がしばらくの間取り組んできたプロジェクトの最後のステップなので、私が得られるあらゆる助けに感謝します。これは私の最初のC#/ VSプロジェクトなので、どんなヒントにも心を開いていますが、この問題を最初に解決することに集中したいと思います。

ありがとう!

22
Emeka

インターネットにリストされている一般的な解決策は、HttpWebRequestのKeepAliveプロパティをfalseに設定することです。根本的な原因が、一定時間後に実際に接続が自動的に閉じられたにもかかわらず、接続が再利用されることが予想される場合、これにより問題を解決できます。ただし、接続を絶えず開いたり閉じたりすると、パフォーマンスが低下します。

この問題が発生したときに使用したもう1つの解決策は、Timeoutプロパティを拡張することでした:WebRequest.ReadWriteTimeout、WebRequest.Timeout、RequestStream.WriteTimeout、およびRequestStream.ReadTimeout。これらはミリ秒単位であることに注意してください。タイムアウトを1000 * 60 * 10にして10分を表すことができます(または、それが何を意味するか知っていると思われる場合は600000にしてください)。ファイルサイズを小さくすることで、これが問題の原因である可能性が高いかどうかをテストできます。

ところで。あなたのコードはリストされたウェブサイトにはもうありません。それでも問題がある場合は、投稿のテキストに含めることをお勧めします。

21
Registered User

ここに私のために働く唯一の解決策があります:

http://blogs.msdn.com/b/johan/archive/2006/11/15/are-you-getting-outofmemoryexceptions-when-uploading-large-files.aspx

これらの行が重要です:

    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(yourUri);
    wr.KeepAlive = false;
    wr.Timeout = System.Threading.Timeout.Infinite;
    wr.ProtocolVersion = HttpVersion.Version10;

そしてここ:

wr.AllowWriteStreamBuffering = false;
12
RoundOutTooSoon

私のアプリケーションの簡単な要約:同時にHTTPリクエストを実行する最大16個の同一のスレッドがあります。これらの各スレッドは、固有のローカルエンドポイントとともに、さまざまなWebサーバーから要求しています。これで、これらの呼び出しを行う関数には、(同じWebサーバーに対して)実行していくつかの集計を行うための3つの連続したHTTP要求があります。

上記のリンクに掲載されている解決策に基づいて、次の組み合わせがうまくいきました。

System.Net.ServicePointManager.DefaultConnectionLimit = 200;
System.Net.ServicePointManager.MaxServicePointIdleTime = 2000;
System.Net.ServicePointManager.MaxServicePoints = 1000;
System.Net.ServicePointManager.SetTcpKeepAlive(false, 0, 0);

HttpWebRequest webRequest1 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
 + "/xslt?");
webRequest1.KeepAlive = false;
webRequest1.Timeout = 2000;
//Do other stuff here...
//Close response stream

Thread.Sleep(1000); //This delay seems to help. Obviously very specific to the server

HttpWebRequest webRequest2 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
 + "/xslt?");
webRequest2.KeepAlive = false;
webRequest2.Timeout = 2000;
//Do other stuff here...
//and so on...
3
tman

モバイルアプリからファイルを受け取り、着信リクエストのストリームを発信HttpWebRequestのストリームにコピーすることにより、それらをAzure BLOBストレージに転送するAzure Webサービスをサポートしています。

using (Stream requestStream = outgoingRequest.GetRequestStream()) 
{ 
    context.Request.InputStream.copyTo(requestStream)
    requestStream.Flush();
    requestStream.Close();
}

Close()の最中、またはClose()を含めない場合は{}の使用の最後に、「リクエストが中止されました:リクエストがキャンセルされました」という例外が時々スローされていました。上記の提案された解決策をすべて試しましたが、ここで共有したいエラーの実際の原因が見つかるまで、どれも機能しませんでした:着信要求のInputStreamが切断され、完全なファイルコンテンツが含まれていない場合があります。この不完全なストリームが送信リクエストのストリームにコピーされると、送信リクエストはClose()中またはusing {}ブロックの最後にエラーをスローします。原因は発信リクエストではないため、これは少し誤解を招く可能性がありますが、
それにコピーされている不完全なストリーム。これを回避する方法は、呼び出し元のアプリからヘッダーに格納する必要があるファイルの長さを比較する着信要求ストリームの長さのチェックを追加することです。

    if (context.Request.InputStream.Length != int.Parse(context.Request.Headers["file-length"])) 
    { 
        //handle this case here, e.g.
        context.Response.StatusCode = 500;
        context.Response.StatusDescription = "(500) Internal Server Error";
        context.Response.End();
    }
    else
    {
         //proceed with copying the stream (the first code snippet)
    }
1
user2116792