WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

応答ヘッダが 64KB を超えるとエラー

by WebSurfer 2. September 2019 12:00

HttpClient を使った HPPT 通信で、応答ヘッダが 64KB を超えると WebException 例外がスローされるという話を備忘録として書いておきます。

(元の話は Teratail のスレッド「GetAsync処理時のメッセージの長さが制限の解消方法について」のもので、実際に自分が経験した訳ではなく聞いた話です)

同様な問題は HttpWebResponse / HttpWebRequest を使った時から起こっていた問題だそうで、応答ヘッダが 64KB を超えると WebException がスローされ、以下のエラーメッセージが出るそうです。

"接続が切断されました: メッセージの長さが制限を超えています。"

英文では、

"The underlying connection was closed: The message length limit was exceeded."

応答ヘッダが 64KB を超えるというのはレアなのか、日本語のエラーメッセージでググっても参考になる記事はヒットしませんでした。

でも、英語圏まで検索範囲を広げる(英文でググる)と HttpWebResponse / HttpWebRequest でこの問題に遭遇した人はいるようで、WebException: "The message length limit was exceeded" 他の記事がヒットします。

その記事に書いてある解決策は、HttpWebRequest の MaximumResponseHeadersLength プロパティを -1 (無制限) に設定することだそうです。(未検証・未確認です)

HttpClient を使う場合は、.NET Framework 4.7.1 以降ですが、HttpClientHandler クラスMaxResponseHeadersLength プロパティを使って応答ヘッダのサイズの許容最大値を設定できるそうです。

// Create an HttpClientHandler object
HttpClientHandler handler = new HttpClientHandler();
handler.MaxResponseHeadersLength = 128;  // 128KB

// Create an HttpClient object
HttpClient client = new HttpClient(handler);

.NET 4.5 では MaxResponseHeadersLength プロパティは使えず .NET 4.7.1 で使えるようになったということは、HttpWebRequest / HttpWebResponse で起こっていた問題に対応できないことを指摘されて追加したのかもしれませんね。(想像です)

Tags: , , ,

.NET Framework

構成ファイルの保存場所

by WebSurfer 1. September 2019 15:33

Windows Forms、WPF、Console アプリの構成ファイルの保存場所はどこかという話を書きます。(元の話は Teratail のスレッド「app.configの情報を書き換えたい」です)

Settings

Visual Studio でアプリケーション開発の際、自動的に App.config というファイルが生成され、それに接続文字列などの設定値が保存されますが、アプリを実行するときに使われる構成ファイルは App.config とは別に生成され、別の場所に保存されます。

まず、アプリをビルドする際、生成される .exe ファイルと同じ場所に、App.config の内容をそのままコピーして <アプリケーション名>.exe.config という名前のファイルが作られます。ただし、この他に構成ファイルが作られるケースがあります。

上の画像は Windows Forms アプリケーションの Settings の内容で、その中の MainWindows_Left, _Top, _Width, _Height はウィンドウのサイズです。ユーザーがウィンドウのサイズを変更してアプリを閉じると変更後の値を保存して、次にアプリを立ち上げたときは保存した値でウィンドウのサイズを設定するようにコーディングしています。

MainWindows_Left, _Top, _Width, _Height のデフォルト値(初期値)は App.config や <アプリケーション名>.exe.config に保存されますが、変更後の値はどこに保存されるでしょう?

ウィンドウのサイズを変更してアプリを閉じても、App.config と <アプリケーション名>.exe.config の MainWindows_Left, _Top, _Width, _Height の値は変わりません。

でも、次にアプリを立ち上げるとサイズは期待通り変更後のサイズになるので、どこかに変更後の MainWindows_Left, _Top, _Width, _Height の値が保存されているはずです。

実は、(1) すべてのユーザーに適用するグローバル構成、(2) ローミング ユーザーに適用する構成、(3) 個々のユーザーに適用する個別構成によって格納場所が違うそうです。

App.config と <アプリケーション名>.exe.config は「(1) すべてのユーザーに適用するグローバル構成」に該当するようです。

変更後の MainWindows_Left, _Top, _Width, _Height の値は「(3) 個々のユーザーに適用する個別構成」に該当するようで、以下のフォルダ下に user.config という名前で保存されています。

C:\Users\<ユーザー名>\AppData\Local\<アプリケーション名>

以下の画像はエクスプローラーで user.config の場所を表示し、その内容をメモ帳で開いて表示したものです。変更後の MainWindows_Left, _Top, _Width, _Height の値が反映されています。

user.config

ちなみに、ファイルパスはプログラムで取得することができます。

ConfigurationManager.OpenExeConfiguration メソッドConfiguration オブジェクトを取得し、その FilePath プロパティを使って取得します。

OpenExeConfiguration メソッドは引数に ConfigurationUserLevel を取るオーバーロードを使用し、ConfigurationUserLevel のフィールドを None, PerUserRoaming, PerUserRoamingAndLocal とすることで、それぞれ上の (1), (2), (3) の Configuration オブジェクトを取得できます。

Tags: ,

.NET Framework

不正なクロススレッドコールの捕捉

by WebSurfer 11. July 2019 16:43

Windows Forms のマルチスレッドアプリで不正なクロススレッドコールがある場合、Visual Studio から[デバッグの開始(S)]でなら以下のような例外が捕捉されるが、[デバッグなしで開始(H)]では捕捉されないという話を書きます。

不正なクロススレッドコールの捕捉

元の話は Teratail の「非同期処理でデバッグ時・ビルド実行時で処理結果が異なる?」というスレッドから来ています。

例えば、Windows Forms アプリの Button.Click のイベントハンドラで、以下のように AsParallel 拡張メソッドを使ってマルチスレッドで処理するケースを考えます。

private void button4_Click(object sender, EventArgs e)
{
    Enumerable.Range(1, 10).AsParallel().ForAll(z =>
    {
        this.textBox2.Text += z.ToString();
    });
}

this.textBox2.Text += z.ToString(); の行で、textBox2 が作成された UI スレッドとは別のスレッドから textBox2 の呼び出しを行っています。これが不正なクロススレッドコールになります。

このコードを Visual Studio から[デバッグの開始(S)]で実行した場合は、デバッガがこの行で InvalidOperationException 例外をスローし、"コントロールが作成されたスレッド以外のスレッドからコントロール 'textBox2' がアクセスされました" というエラーメッセージを表示します。それが上の画像です。

ところが[デバッグなしで開始(H)]で実行した場合は例外はスローされず、あたかもこのコードは正常終了したかのように見えます。集約的例外ハンドラで捕捉してアプリケーションを終了させるということもできません(そもそも例外がスローされないので)。

という訳で、特にマルチスレッドアプリを開発している場合は必ず[デバッグの開始(S)]で実行して動作確認をするようにした方がよさそうです。

なお、[デバッグなしで開始(H)]でも CheckForIllegalCrossThreadCalls プロパティを true(デフォルトは false)に設定すれば不正なクロススレッドコールで例外をスローさせることはできます。

でも、たぶんオーバーヘッドが増えてパフォーマンスに影響があるでしょうからリリース前には元に戻さなければならず、そんな面倒なことをするより[デバッグの開始(S)]で実行して確認するのが正解だと思います。

Tags:

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  October 2019  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar