C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: HttpClient「要求メッセージは送信済みです」対処方法


(過去ログ 172 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■99207 / inTopicNo.1)  HttpClient「要求メッセージは送信済みです」対処方法
  
□投稿者/ 朱里 (1回)-(2022/02/21(Mon) 00:51:06)

分類:[C#] 

初めまして、掲示板初めて使わせていただきます。
マルチスレッドでこちらのクラスを複数回使用して動いてはいるんですが、ウェブサイトが500エラー等なんらかのエラーでリトライで再取得を試みようとすると
System.InvalidOperationException 「要求メッセージは送信済みです。同じ要求メッセージは複数回送信できません。」
で全てのスレッドのヘッダーを取得してくれなくなります。(恐らくSendAsync()で止まってる)
エラーが発生した際に再度取得するようにしているつもりが、それが上手く働いてないようです。

&#8212;以下コード-

class GetFile
    {
        private string Error = ""; //エラー表示
        bool RetryFlg = false; //リトライ処理
        public GetFile()
        {
           httpClient.Timeout = TimeSpan.FromMilliseconds(3000);
        }
        HttpClient httpClient = new HttpClient();
        HttpRequestMessage headMessage;
        HttpResponseMessage response;
        int ErrorCount = 0;
        public string GetETag(string URL)//Etagの取得
        {
            try
            {
                string str= $"{URL}?{DateTime.Now.Ticks}";
                headMessage = new HttpRequestMessage(HttpMethod.Head, str);
                response = httpClient.SendAsync(headMessage).Result;
                switch (response.StatusCode)
                {
                    case HttpStatusCode.OK: //取得できた時
                        ErrorCount = 0;
                        return response.Headers.ETag?.Tag;
                    case HttpStatusCode.NotFound: //404の時
                        RetryFlg = false;
                        return null; 
                    default: //500等のサーバーエラーの時
                        Error = $"ErrorCode : {response.StatusCode}";
                        ErrorCount++;
                        RetryFlg = true;
                        return null;
                }
            }
            catch (Exception ex)
            {
                RetryFlg = true;
                Error = $"{ex.TargetSite}{ex.Message}";
                ErrorCount++;
                if (ErrorCount >= 100) //100回エラー発生でリトライ処理無効
                {
                    ErrorCount = 0;
                    RetryFlg = false;
                }
                Console.WriteLine($"WARN : {ex}");
            }
            return null;
        }
    }

引用返信 編集キー/
■99208 / inTopicNo.2)  Re[1]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ くま (167回)-(2022/02/21(Mon) 04:05:41)
朱里 さん

「GetFile」クラスを動かしている所の記載がないと判断できません
可能性としては
https://www.w2solution.co.jp/tech/2019/12/18/httpclient%E3%82%92using%E3%81%97%E3%81%9F%E3%82%89%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E8%A9%B1/

でしょうか。
引用返信 編集キー/
■99209 / inTopicNo.3)  Re[1]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ WebSurfer (2449回)-(2022/02/21(Mon) 06:38:49)
No99207 (朱里 さん) に返信

何を作っているか (WinForms? WPF? ASP.NET Web アプリ?) と開発環境を書いてください。

> マルチスレッドでこちらのクラスを複数回使用して

どこがどのようにマルチスレッドなのですか?

async/awat を使ってないのは何故ですか?
引用返信 編集キー/
■99210 / inTopicNo.4)  Re[2]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ 朱里 (2回)-(2022/02/21(Mon) 09:11:26)
おはようございます。初心者だったもので申し訳ございません。

2 こちらのサイトを一度拝見させていただきましたが、GetFileはFormsクラスの場所に配置しているのでソケットの浪費等とは関係ない可能性があります。
実装方法としてはこのようになっています。簡略化した物なので変数とかが抜けてる可能性があります。

3 申し訳遅れました。 Windows Formでの動作となります。
初期化処理で複数のスレッドを立ち上げてFormsクラスに配置されているGetFileクラスを使いまわししている感覚になります。

初めて使用した者ですが迷惑投稿者と判定されて投稿に苦戦しました。

何度投稿しても誤判定されるようなのでコードはこちらに載せます
https://raw.githubusercontent.com/Misaki0331/Misaki0331.github.io/main/test/test.cs

引用返信 編集キー/
■99211 / inTopicNo.5)  Re[3]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ WebSurfer (2450回)-(2022/02/21(Mon) 09:33:57)
No99210 (朱里 さん) に返信

先のレスでもお願いしましたが・・・

開発環境を書いてください。開発環境というのは OS, Visual Studio のバージョン、
.NET Framework か Core のどっちかとそのバージョンなどの情報。

async/awat を使ってないのは何故ですか?

以下追加質問ですが、

そもそもリトライは意味がないのではないですか?

HTTP 404 応答は URL が間違っているから見つからないと Web サーバーが言っている
のだから同じ URL で何度リトライしても意味がないはずですので。

HTTP 500 も 5 分ぐらい待ってリトライするならともかく、短期間では何度リトライし
ても同じ結果になると思いますので。


> マルチスレッドでこちらのクラスを複数回使用して動いてはいるんですが、

試しにマルチスレッドでなく単一スレッドでクラスのインスタンスは一つのみ生成して
同じようにリトライしたらどうなりますか?


同時接続数には制限があると思いますが、そのあたりの影響は考えていますか? HTTP 1.1
仕様では同時接続は 2 つまでとなっています。HttpClient は試してないですが、HttpWebRequest
を使った場合その制約が適用されるということがありました。
引用返信 編集キー/
■99212 / inTopicNo.6)  Re[3]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ WebSurfer (2451回)-(2022/02/21(Mon) 10:01:53)
No99210 (朱里 さん) に返信

> 何度投稿しても誤判定されるようなのでコードはこちらに載せます
> https://raw.githubusercontent.com/Misaki0331/Misaki0331.github.io/main/test/test.cs

コードを拝見しましたが、以下の記事の最初の図にある Thread の時代まで
戻っちゃってませんか?

第1回 .NET開発における非同期処理の基礎と歴史
https://atmarkit.itmedia.co.jp/fdotnet/chushin/masterasync_01/masterasync_01_02.html

何故でしょう?
引用返信 編集キー/
■99213 / inTopicNo.7)  Re[4]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ 朱里 (3回)-(2022/02/21(Mon) 10:05:08)
No99211 (WebSurfer さん) に返信
そうでした、すみません。
.Net Framework 4.7.2
Visual Studio Community 2019 Version 16.11.5
を使用しています。
Async Awaitを使っていない理由としてはまだよく分かっていない状態なので、取り合えずThreadをnewして実行させて破棄している状態です。
もしかしたらこちらで記しているコードに問題があるとは思いますが、404エラーは何もしない、他のエラーは自動でリトライするようにしております。
今取得しようとしているサイト内では500エラーが起きても数秒で復活するようになっています。

>試しにマルチスレッドでなく単一スレッドでクラスのインスタンスは一つのみ生成して
>同じようにリトライしたらどうなりますか?
スレッドが死ぬだけで他のスレッドは問題なかったです。
それと同時にエラーが起きた時にGetFileをnewするとHttpClientは再初期化されるので問題は発生せず解決しました。

>同時接続数には制限があると思いますが、そのあたりの影響は考えていますか?
全く考えていないです。20個程度マルチスレッドで動かしていますが、問題なくヘッダーが効率的に取得できている状態です。
引用返信 編集キー/
■99214 / inTopicNo.8)  Re[5]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ WebSurfer (2452回)-(2022/02/21(Mon) 10:17:53)
No99213 (朱里 さん) に返信

> Async Awaitを使っていない理由としてはまだよく分かっていない状態なので、取り合えずThreadをnewして実行させて破棄している状態です。

自分にとってはすでに忘却の彼方的な Thread を使ったコードを読む気力が沸いてこないです。
お役に立てずすみませんが他の方の回答をお待ちください。
引用返信 編集キー/
■99215 / inTopicNo.9)  Re[4]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ 朱里 (5回)-(2022/02/21(Mon) 10:22:10)
No99214 (WebSurfer さん) に返信
WebSurferさん、ご回答ありがとうございました。
結果的に問題は解決しましたのでこちらのスレッドは解決済みにさせていただきます。
解決済み
引用返信 編集キー/
■99222 / inTopicNo.10)  Re[5]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ 古谷 (34回)-(2022/02/21(Mon) 20:24:52)
送信済みか否かの情報はHttpRequestMessageが持ってるみたいね

https://github.com/microsoft/referencesource/blob/master/System/net/System/Net/Http/HttpRequestMessage.cs
|
| // If this field is 0 (default), then the message wasn't sent by an HttpClient instance yet. If the field
| // value is 'messageSent', then the message was already sent and should not be sent again.
| private int sendStatus;

なので、リトライ時にHttpRequestMessageのインスタンスを再作成すればOKな感じ

// NG
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://www.google.co.jp/");
client.SendAsync(request).Wait();
client.SendAsync(request).Wait();

// OK
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://www.google.co.jp/");
client.SendAsync(request).Wait();
request = new HttpRequestMessage(HttpMethod.Get, "https://www.google.co.jp/");
client.SendAsync(request).Wait();

引用返信 編集キー/
■99223 / inTopicNo.11)  Re[6]: HttpClient「要求メッセージは送信済みです」対処方法
□投稿者/ 古谷 (35回)-(2022/02/21(Mon) 20:25:34)
解決済みにチェック
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -