質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

4724閲覧

C# StreamWriterで動作はするがファイルに情報が書き込まれない

AMK

総合スコア765

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1グッド

1クリップ

投稿2023/06/10 09:14

編集2023/06/10 09:54

実現したいこと

StreamWriterでデータをCSVに書き込めるようにしたい

環境

Windows10 Pro(バージョン 21H2)

Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.6.2

WinFormsにて作成しています。
.net7.0

試したこと

昨日まで動いていたが、今日になって動かなくなった

3日前にZIPで送ったコードが残っていたので解凍してそのコードを実行しても動かない

昨日寝る前にVisual Studioのアップデートを行って寝ました。

下記のコードは、メインのコードからCSV部分だけを抜き出してテストで再構築したコードです。

そこで解った事は、54行目のTask.Delay(1000).Wait();を消すと一気にデータが書き込まれてデータは正常に書き込まれるが
Task.Delay(1000).Wait();を追加すると見た目は動いているが実際はヘッダー行すらデータが書き込まれない状況です。

そもそも、私のコードが悪くてタマタマ動いていたのか?アップデートの影響で動かなくなったのか?教えていただきたいです。

知りたいこと

アップデートの影響ならば、ダウングレードの方法が知りたいです。

codeが悪いのであれば、指摘よろしくお願いします。

code

C#

1//プログラム実行 2Task t1 = Task.Run(() => { main_system(label1, textBox1, progressBar1, ref Flags.Cancel_Flag1, ref Flags.End_Flag1); }); 3 4//実行部分 5private void main_system2(Control label, Control textbox, ProgressBar progressBar, ref bool Cancel_Flag, ref bool End_Flag) 6 { 7 if (textbox.Text == "") 8 { 9 MessageBox.Show("CSVファイルを選択してください。"); 10 } 11 else 12 { 13 string inputFile = textbox.Text; 14 string file_name = Path.GetFileName(inputFile); 15 DateTime dt = DateTime.Now; 16 String Output_File_Name = dt.ToString($"{dt:完了_HH-mm-ss_}") + file_name; 17 string main_folder = System.IO.Directory.GetCurrentDirectory(); 18 string outputFile = main_folder + "\\" + Output_File_Name; 19 20 // Shift JISで書き込むためのエンコーディングを取得 21 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 22 Encoding enc = Encoding.GetEncoding("sjis"); 23 24 // CSVファイルを読み込む 25 string[] lines = System.IO.File.ReadAllLines(inputFile, enc); 26 27 28 // ヘッダー行を取得 29 string headerLine = lines[0]; 30 int max_line = lines.Length - 1; 31 32 //別スレッドからコントロールを操作する場合はInvokeを使う 33 this.Invoke(new Action(() => 34 { 35 //プログレスバー初期化 36 progressBar.Minimum = 0; 37 progressBar.Maximum = max_line; 38 progressBar.Value = 0; 39 })); 40 41 42 43 44 // 書き込み用のファイルを作成 45 using (StreamWriter writer = new StreamWriter(outputFile, false, enc)) 46 { 47 48 // ヘッダー行を追加 49 writer.WriteLine(headerLine + ",判定結果"); 50 // データ行を書き込む 51 for (int i = 1; i < max_line + 1; i++) 52 { 53 54 Task.Delay(1000).Wait(); //sleep 55 //別スレッドからコントロールを操作する場合はInvokeを使う 56 this.Invoke(new Action(() => 57 { 58 //ステータス更新 59 label.Text = String.Format("{0}/{1}件", i.ToString(), max_line.ToString()); 60 progressBar.Value = i; 61 })); 62 63 // カンマで区切られたデータを分割 64 string[] values = lines[i].Split(','); 65 string hantei = i.ToString(); 66 try 67 { 68 this.Invoke(new Action(() => 69 { 70 label.Text = "CSV書き込み中"; 71 })); 72 writer.WriteLine(string.Join(",", values) + "," + hantei); 73 74 } 75 catch 76 { 77 MessageBox.Show("CSVファイルが開かれています、閉じてください。"); 78 writer.WriteLine(string.Join(",", values) + "," + hantei); 79 } 80 81 } 82 } 83 } 84 }
sreを押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/06/10 09:24

何を作っているか(WinForms? その他?)とターゲットフレームワークを書いてください。 何故 Task.Run を使っているのですか? Task.Delay(1000).Wait(); とか何のつもりなのでしょう? 意味無さそうな気がしますけど。
AMK

2023/06/10 09:53 編集

質問ありがとうございます >何故 Task.Run を使っているのですか? 同じような処理を複数走らせる予定です。 >Task.Delay(1000).Wait(); とか何のつもりなのでしょう? 処理が早すぎて、データの取得先に負荷がかかるので処理を数秒間止めたくて追加しました やり方間違ってますか?他の方法があるのでしょうか?指摘していただけると幸いです。
AMK

2023/06/10 09:53

>何を作っているか WinFormsです。 >ターゲットフレームワークを書いてください。 .net7.0です。
YAmaGNZ

2023/06/10 10:48

Task.Runにてmain_systemを呼んでいますが提示されたコードにはmain_system2しかありません。 提示されたコードが動いているのですか?デバッグ用とかで別の物あってそこを変更してるとかありませんか?
退会済みユーザー

退会済みユーザー

2023/06/10 10:59 編集

はっきり言わせていただけると、分かってやっているとは思えず、たぶん話が通じないと思います。済みませんが、撤退します。 思い出しましたが、あなたは前にも意味不明な質問をして、こちらから質問しても答えず、スレッドを放置しましたよね。また同じことになるのですか? https://teratail.com/questions/sfw9pxfbcru6yj
AMK

2023/06/10 12:10

>Task.Runにてmain_systemを呼んでいますが提示されたコードにはmain_system2しかありません。 すみません、転記ミスです。 codeは動いています。
AMK

2023/06/10 12:13

>たぶん話が通じないと思います。済みませんが、撤退します。 その節はご迷惑をおかけしました。
AMK

2023/06/10 17:28

情報ありがとうございます。 調べてみます!
AMK

2023/06/10 17:36

Task.Run(() => { main_system2(label1, textBox1, progressBar1, ref Flags.Cancel_Flag1, ref Flags.End_Flag1); }).ConfigureAwait(false); コチラで試してみましたが状況変わらずでした。
odataiki

2023/06/11 03:36

アップデートの影響でそうなったのかわかりませんが、 再インストールするしかないと思います。 https://learn.microsoft.com/en-us/answers/questions/1164611/downgrade-visual-studio >コードが悪い場合 質問者さんの意図した動きになっていない、ということだと思いますが 何を意図しているのか質問文からはいまいち分かりません。 なので何をどうすれば良いのかのアドバイスがしにくい質問文になっているように思います。 54行目消しても動くならそれでいいんじゃないかと・・・ (プログラムを速く実行させ完了させた方が負荷減るんじゃない?って思いました)
AMK

2023/06/11 11:35

回答ありがとうございます。 後出しの情報ですみません。 スクレイピングした結果を入れるので、相手方のサーバー負荷対策に入れる予定です。 他にもウェブ表示待ちで止めたり、色々使っています。 今回提出したコードは、原因特定するために本番codeから一部抜き出したコードです。 原因特定までは出来たのですが改善策が全く分からなかったので、今回の質問に至りました。
退会済みユーザー

退会済みユーザー

2023/06/11 21:55

撤退すると言っておきながら何ですが・・・ スクレイピングは、サイトの管理者に許可を得ているとか、規約に従って専用の API にアクセスしているとかでなければ、迷惑行為になるかもしれないということは認識してますか? クローラーを作って某図書館サイトにアクセスしたら業務妨害とかで逮捕された事例もありますので、甘く見ない方がいいと思います。 逮捕までいかなくても、被害が深刻な場合は損害賠償の訴訟を受けるかもしれません。 訴訟までいかなくても、アクセス遮断ならWeb サーバーの設定で可能なので、多分に可能性はあると思います。帯域ごと遮断され、あなたのやったことで多数の利用者が巻き添えを喰らうことになるかもしれません。 その辺りはどうなっているのでしょう?
AMK

2023/06/12 08:36

ご忠告ありがとうございます。 肝に銘じておきます。 一応念のため、海外のプライベートプロキシサーバー経由でのスクレイピングにしております。
退会済みユーザー

退会済みユーザー

2023/06/12 09:17

> 一応念のため、海外のプライベートプロキシサーバー経由でのスクレイピングにしております。 バレないから大丈夫だと言ってますか? そういうことを言われると、反社会的な匂いまでしてきます。
AMK

2023/06/12 09:34

意味ないかもしれないですが、.NET Frameework4.7で1から作り直して上記コードを走らせてみます。 動かなかったらコード自体が悪いという事で、コードを調べなおします。
AMK

2023/06/12 09:35

引き続き、ご協力いただける方がいらっしゃいましたらよろしくお願いします。
退会済みユーザー

退会済みユーザー

2023/06/12 09:40

回答するのは迷惑行為の手助けをすることになるかも。
AMK

2023/06/12 09:58

.NET Frameework4.7で作り直した結果、CSVの書き込みは出来るようです ただ、70行目のCSV書き込みはラベルに表示されるが59行目のSTATUSの更新内容は表示されない Task.Delay(1000).Wait();に関しても Task.Delay(10000);に変更してWait();を取って数を増やしても秒数は待たずに一気に最後まで動きます。 (この症状は、net7.0でも同じ症状だったともいます。) 引き続き、ご協力いただける方がいらっしゃいましたらよろしくお願いします。
AMK

2023/06/12 10:00

.net7.0で作り直してみます
AMK

2023/06/12 10:33

.net7.0で作り直した結果、.NET Frameework4.7と同様、CSV書き込みはするのですが CSV書き込み中の表示からSTATUS更新のラベルへデータ更新が出来ないです。 STATUS更新の後にTask.Delay(3000).Wait();を入れたらCSV書き込み中の文字が点滅するだけで STATUS状況が読めない状況です。 SurferOnWwwさんの指摘通り >何故 Task.Run を使っているのですか? >Task.Delay(1000).Wait(); とか何のつもりなのでしょう?  他のスレッド処理の方法も調べて実装してみます。
guest

回答1

0

自己解決

とりあえずCSVは書き込めたので、いったん閉じます。
協力してくれた方々、ありがとうございました。

チャットGPTに質問したらCSV書き込まない問題が解決したのでデータを共有します。
(ラベルのテキストは更新されないのは、そのまま)
<以下チャットGPT>
C#のStreamWriter.WriteLineメソッドは、データを書き込む際にバッファリングを行います。そのため、データがバッファに蓄積され、一定のサイズに達したときや書き込みが明示的にフラッシュされたときにまとめて書き込まれることがあります。その結果、1件ずつの書き込みではなく、まとめて書き込まれることがあります。

これを解決するには、以下の方法を試してみることができます:

StreamWriter.AutoFlushプロパティを有効にする: StreamWriterのAutoFlushプロパティをtrueに設定することで、WriteLineメソッドが呼び出されるたびに自動的にフラッシュされるようになります。これにより、データがバッファにたまることなく即座に書き込まれます。

C#

1using (StreamWriter writer = new StreamWriter(filePath, true) { AutoFlush = true }) 2{ 3 // WriteLineの呼び出しで即座に書き込みが行われる 4 writer.WriteLine(line); 5}

<プラン2>
StreamWriter.Flushメソッドを明示的に呼び出す: StreamWriterのFlushメソッドを呼び出すことで、現在のバッファ内のデータを即座に書き込むことができます。

C#

1using (StreamWriter writer = new StreamWriter(filePath, true)) 2{ 3 // WriteLineの呼び出し後にFlushを呼び出してバッファを明示的にフラッシュする 4 writer.WriteLine(line); 5 writer.Flush(); 6} 7

上記のいずれかの方法を使用すると、WriteLineメソッドが呼び出された時点でデータが即座に書き込まれるようになります。これにより、1件ずつの書き込みが実現されます。

なお、ファイルのオープンやクローズなどのエラーハンドリングも適切に行ってください。

投稿2023/06/12 11:55

編集2023/06/12 13:39
AMK

総合スコア765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問