C# と VB.NET の質問掲示板
ASP.NET、C++/CLI、Java 何でもどうぞ
C# と VB.NET の入門サイト
掲示板トップ
C# と VB.NET のサンプル
新規作成
利用方法/規約
ツリー表示
トピック表示
ランキング
記事検索
過去ログ
■103929
/ 1階層)
FormClosingでセーブするが稀に最後まで書込まれない
□投稿者/ 魔界の仮面弁士
(3910回)-(2026/05/05(Tue) 17:57:18)
■
No103927
(Tom さん) に返信
> ただ件数がいま50万行をこえており書き込みに数秒かかります。
1行2000文字超 × 50万行だと、最大で約10億文字(2GB弱)換算ですね?
> この50万件のデータを書き込む関数のあとに数十行のデータを書き込む関数を呼んでいるのです
同一ファイルへの追記 (上書きではない) と思ってよいでしょうか。
それぞれの関数が、同一の Stream インスタンスに対して書き込んでいるのか、
あるいはファイル名のみが共有されており、それぞれの関数内で
書き込んでは都度 Close している処理なのかでも話が変わってきそうですが。
> もしかして最後まで書き終わる前にプロセスおわっちゃう?なんて思ったのですが、
OS の Write Cache 書き込みの遅延が原因では無いでしょうか。
通常、StreamWriter.Flush() や Close() を呼んだだけでは、データは
.NET のバッファから OS のバッファに移るだけで、そこから
物理ディスクへの書き込み完了については OS のタイミングに委ねられます。
まずは FileStream.Flush(true) を試してみてください。
これは FlushFileBuffers API に相当する機能で、OS に対して
「ディスク装置のキャッシュもフラッシュせよ」という指示を行うものです。
using (var fs = new FileStream(csvFileName, FileMode.Create, FileAccess.Write))
using (var st = new StreamWriter(fs, System.Text.Encoding.GetEncoding("Shift_JIS")))
{
//
// 元の書き込み処理をここに記述
//
st.Flush(); // StreamWriter(アプリ層) のバッファを FileStream (OS層) へ
fs.Flush(true); // OS のバッファを物理ディスクへ強制フラッシュ
}
この時、Flush(true) の前に Flush() を先に呼ぶようにしないと、
StreamWriter 内に残っているデータが OS に渡されないのでご注意を。
なお、Close() メソッドは内部で Flush() を呼びますが、
これは Flush(true) の呼び出しを含みません。
そのため、Flush(true) は明示的な呼び出しが必要です。
https://learn.microsoft.com/ja-jp/dotnet/api/system.io.filestream.flush?WT.mc_id=DT-MVP-8907&view=netframework-4.8.1
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs#L195
別案として…そもそも Write Cache を使わないという選択肢もあります。
FileOptions.WriteThrough を指定することで、Write Cache 無しで
直接ディスクに書き込める方法 (Unbuffered I/O) です。
ただし書き込んでいる間、システム全体のパフォーマンスが低下する可能性があります。
2GB 弱の書き込みにこれを使うと、数秒どころか分単位で待たされるかもしれません。
この機能はログやトランザクションなど、
データの整合性が速度よりも優先される場合に用いられるオプションです。
using (var fs = new FileStream(csvFileName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.WriteThrough))
using (var st = new StreamWriter(fs, System.Text.Encoding.GetEncoding("Shift_JIS")))
{
// 書き込み処理
}
編集キー/
編集
前の記事
(元になった記事)
次の記事
(この記事の返信)
←FormClosingでセーブするが稀に最後まで書込まれない
/Tom
→Re[2]: FormClosingでセーブするが稀に最後まで書込まれない
/魔界の仮面弁士
上記関連ツリー
FormClosingでセーブするが稀に最後まで書込まれない
/ Tom
(26/05/05(Tue) 11:26)
#103927
└
FormClosingでセーブするが稀に最後まで書込まれない
/ 魔界の仮面弁士
(26/05/05(Tue) 17:57)
#103929
←Now
└
Re[2]: FormClosingでセーブするが稀に最後まで書込まれない
/ 魔界の仮面弁士
(26/05/05(Tue) 18:53)
#103930
└
Re[3]: FormClosingでセーブするが稀に最後まで書込まれない
/ Tom
(26/05/06(Wed) 13:09)
#103931
└
Re[4]: FormClosingでセーブするが稀に最後まで書込まれない
/ Tom
(26/05/13(Wed) 20:50)
#103933
└
Re[5]: FormClosingでセーブするが稀に最後まで書込まれない
/ Azulean
(26/05/13(Wed) 22:06)
#103934
└
Re[6]: FormClosingでセーブするが稀に最後まで書込まれない
/ 魔界の仮面弁士
(26/05/14(Thu) 11:41)
#103935
└
Re[7]: FormClosingでセーブするが稀に最後まで書込まれない
/ Tom
(26/05/16(Sat) 12:54)
#103936
上記ツリーを一括表示
/
上記ツリーをトピック表示
上記の記事へ返信
入力内容にタグは利用できません。
他人を中傷する記事は管理者の判断で予告無く削除されます。
半角カナは使用しないでください。文字化けの原因になります。
名前、コメントは必須記入項目です。記入漏れはエラーになります。
入力内容の一部は、次回投稿時の手間を省くためブラウザに記録されます。
URL は自動的にリンクされます。
記事中に No*** のように書くとその記事にリンクされます(No は半角英字/*** は半角数字)。
名前
(*必須)
E-Mail (任意)
Web サイト (任意)
投稿モード
通常モード
図表モード (ソースコードを貼る場合はこちらを使用)
本文
(質問の場合は、開発環境・使用言語のバージョンなどを最初に書いてください)
■No103929 (魔界の仮面弁士 さん) に返信 > ■No103927 (Tom さん) に返信 >>ただ件数がいま50万行をこえており書き込みに数秒かかります。 > > 1行2000文字超 × 50万行だと、最大で約10億文字(2GB弱)換算ですね? > >>この50万件のデータを書き込む関数のあとに数十行のデータを書き込む関数を呼んでいるのです > 同一ファイルへの追記 (上書きではない) と思ってよいでしょうか。 > > それぞれの関数が、同一の Stream インスタンスに対して書き込んでいるのか、 > あるいはファイル名のみが共有されており、それぞれの関数内で > 書き込んでは都度 Close している処理なのかでも話が変わってきそうですが。 > > >>もしかして最後まで書き終わる前にプロセスおわっちゃう?なんて思ったのですが、 > OS の Write Cache 書き込みの遅延が原因では無いでしょうか。 > > 通常、StreamWriter.Flush() や Close() を呼んだだけでは、データは > .NET のバッファから OS のバッファに移るだけで、そこから > 物理ディスクへの書き込み完了については OS のタイミングに委ねられます。 > > まずは FileStream.Flush(true) を試してみてください。 > これは FlushFileBuffers API に相当する機能で、OS に対して > 「ディスク装置のキャッシュもフラッシュせよ」という指示を行うものです。 > > using (var fs = new FileStream(csvFileName, FileMode.Create, FileAccess.Write)) > using (var st = new StreamWriter(fs, System.Text.Encoding.GetEncoding("Shift_JIS"))) > { > // > // 元の書き込み処理をここに記述 > // > st.Flush(); // StreamWriter(アプリ層) のバッファを FileStream (OS層) へ > fs.Flush(true); // OS のバッファを物理ディスクへ強制フラッシュ > } > > この時、Flush(true) の前に Flush() を先に呼ぶようにしないと、 > StreamWriter 内に残っているデータが OS に渡されないのでご注意を。 > > なお、Close() メソッドは内部で Flush() を呼びますが、 > これは Flush(true) の呼び出しを含みません。 > そのため、Flush(true) は明示的な呼び出しが必要です。 > https://learn.microsoft.com/ja-jp/dotnet/api/system.io.filestream.flush?WT.mc_id=DT-MVP-8907&view=netframework-4.8.1 > https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs#L195 > > > 別案として…そもそも Write Cache を使わないという選択肢もあります。 > FileOptions.WriteThrough を指定することで、Write Cache 無しで > 直接ディスクに書き込める方法 (Unbuffered I/O) です。 > > ただし書き込んでいる間、システム全体のパフォーマンスが低下する可能性があります。 > 2GB 弱の書き込みにこれを使うと、数秒どころか分単位で待たされるかもしれません。 > > この機能はログやトランザクションなど、 > データの整合性が速度よりも優先される場合に用いられるオプションです。 > > using (var fs = new FileStream(csvFileName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.WriteThrough)) > using (var st = new StreamWriter(fs, System.Text.Encoding.GetEncoding("Shift_JIS"))) > { > // 書き込み処理 > }
編集キー
自分の投稿を編集する時に必要です
(半角8文字以内)
解決済み
/
解決したらチェックしておきましょう。
プレビュー/
管理者用
-
Child Tree
-