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

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

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

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

Q&A

解決済

3回答

3381閲覧

OpenCVで二値化処理を繰り返したところメモリリーク発生

oikawasouta

総合スコア6

C#

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

0グッド

0クリップ

投稿2023/01/11 14:10

編集2023/01/14 02:26

バージョン

Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.2.2
.NETframeworkにて作成

内容

OpenCVにて二値化処理を1000回行い、その時間を計測するプログラムを作成しました。
しかし、プログラムを実行したところメモリリークの影響でエラーが発生してしまいます。

###エラーメッセージは以下です。画像にて失礼します。
イメージ説明

使用した画像のサイズ:258 KB

イメージ説明

該当のソースコード

C#

1//インストール済みライブラリ 2//OpenCVSharp4 3//OpenCVShaerp4.Extensions 4//OpenCVSharp4.runtime.win 5 6using System; 7using System.Collections.Generic; 8using System.ComponentModel; 9using System.Data; 10using System.Drawing; 11using System.Linq; 12using System.Text; 13using System.Threading.Tasks; 14using System.Windows.Forms; 15using System.Diagnostics; //ストップウォッチクラス使用の為記載 16//以下、OpenCvsharpの使用とMatの変換用として追加 17using OpenCvSharp; 18using OpenCvSharp.Extensions; 19 20 21namespace OpenCV_メモリリークデバッグ用 22{ 23 public partial class Form1 : Form 24 { 25 Mat image; 26 Stopwatch sw = new Stopwatch(); // ストップウォッチオブジェクト生成 27 28 public Form1() 29 { 30 InitializeComponent(); 31 } 32 33 private void Form1_Load(object sender, EventArgs e) 34 { 35 pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; 36 } 37 38 private void BtnLoad_Click(object sender, EventArgs e) 39 { 40 var ofd = new OpenFileDialog(); 41 //ファイルフィルタ 42 ofd.Filter = "Image File(*.bmp,*.jpg,*.png,*.tif)|*.bmp;*.jpg;*.png;*.tif|Bitmap(*.bmp)|*.bmp|Jpeg(*.jpg)|*.jpg|PNG(*.png)|*.png"; 43 //ダイアログの表示 44 if (ofd.ShowDialog() == DialogResult.OK) 45 { 46 string image_path = ofd.FileName; //選択した画像のパスを取得 47 image = Cv2.ImRead(image_path); //ImRead関数で画像を読み込む 48 pictureBox1.Image = BitmapConverter.ToBitmap(image); //MatをBitmapへ変換し pictureBox1で表示させる 49 } 50 } 51 52 private void BtnStart_Click(object sender, EventArgs e) 53 { 54 Bitmap pic = null; 55 56 sw.Start(); //時間計測スタート 57 58 for (int i=0; i<100; i++) 59 { 60 //グレー化 61 var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); 62 //二値化 63 var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); 64 pic = BitmapConverter.ToBitmap(thresholdImege); //MatをBitmapへ変換 65 } 66 pictureBox1.Image = pic; 67 68 sw.Stop();//時間計測ストップ 69 Console.WriteLine(sw.Elapsed);//計測時間表示 70 } 71 } 72}

試したこと

①ピクチャーボックスのメモリ開放なども試しました。が変わらず。
以下の内容を55行に追加し試しました。
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}

最後に

諸事情により、1000回処理した時間を計測したかったのですが、そもそもPCの性能的に無理なのでしょうか。

ご教示お願いいたします。

追記  SurferOnWwwさんのサンプルプログラム反映後

//インストール済みライブラリ //OpenCVSharp4 //OpenCVShaerp4.Extensions //OpenCVSharp4.runtime.win using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; //ストップウォッチクラス使用の為記載 //以下、OpenCvsharpの使用とMatの変換用として追加 using OpenCvSharp; using OpenCvSharp.Extensions; namespace OpenCV_メモリリークデバッグ用 { public partial class Form1 : Form { Mat image; Stopwatch sw; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; } private void BtnLoad_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); //ファイルフィルタ ofd.Filter = "Image File(*.bmp,*.jpg,*.png,*.tif)|*.bmp;*.jpg;*.png;*.tif|Bitmap(*.bmp)|*.bmp|Jpeg(*.jpg)|*.jpg|PNG(*.png)|*.png"; //ダイアログの表示 if (ofd.ShowDialog() == DialogResult.OK) { string image_path = ofd.FileName; //選択した画像のパスを取得 image = Cv2.ImRead(image_path); //ImRead関数で画像を読み込む pictureBox1.Image = BitmapConverter.ToBitmap(image); //MatをBitmapへ変換し pictureBox1で表示させる } } private void BtnStart_Click(object sender, EventArgs e) { sw = new Stopwatch(); // ストップウォッチオブジェクト生成 Bitmap pic = null; sw.Start(); //時間計測スタート for (int i=0; i<1000; i++) { //グレー化 using (var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY)) //二値化 using (var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary)) { pic = BitmapConverter.ToBitmap(thresholdImege); pictureBox1.Image = pic; } } sw.Stop();//時間計測ストップ Console.WriteLine(sw.Elapsed);//計測時間表示 } } }

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

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

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

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

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

odataiki

2023/01/11 14:33

VisualStudioが出すエラーメッセージを(抜粋せず、内容は出来るだけそのまま)質問文に追記することは出来ますか?
oikawasouta

2023/01/11 14:37

かしこまりました!ありがとうございます!
odataiki

2023/01/11 14:55

追記ありがとうございます。 追記してもらった画像中に青色文字で「詳細の表示」の部分がクリックできると思います、 その情報も掲載可能でしょうか?
oikawasouta

2023/01/11 22:20

odataikiさん コメントありがとうございます!詳細こちらです。 OpenCvSharp.OpenCVException HResult=0x80131500 Message=Failed to allocate 1637624 bytes Source=<例外のソースを評価できません> スタック トレース: <例外のスタック トレースを評価できません> この例外は、最初にこの呼び出し履歴 [外部コード] OpenCV_メモリリークデバッグ用.Form1.BtnStart_Click(object, System.EventArgs) (Form1.cs 内) [外部コード] OpenCV_メモリリークデバッグ用.Program.Main() (Program.cs 内) でスローされました
dameo

2023/01/12 00:55

リソースリークというやつですね。 https://en.wikipedia.org/wiki/Resource_leak 手元の環境でちょっと試したところ32bitだと特にすぐになくなります。64bitだとなかなかなくなりませんが、なくなるときはほとんどフリーズした感じになる場合が多いです… 画像は以下のオリジナルサイズを使ったところ32bitでは20回くらいでパンクしてました。 https://unsplash.com/ja/%E5%86%99%E7%9C%9F/tfjKJ_gN39E 解決策はYAmaGNZさんのおっしゃるように開放=BitmapもMatもDisposeしてあげるか、usingで宣言しないと駄目です。 原因はどちらもunmanagedなリソースを持っているので、能動的にDisposeしないとそれらがgcから破棄される前にリソースが足りなくなるからです。やり方はちょっと違いますが、OpenCVSharpのサンプルコードでもusingを使っていますよ。 https://github.com/shimat/opencvsharp_samples/blob/master/SamplesCore/Samples/BinarizerSample.cs
退会済みユーザー

退会済みユーザー

2023/01/13 02:46

回答欄に追加質問を書いたようですが、そういうことをされると質問と回答がゴッチャになって訳がわからなくなるので避けてください。 質問者さんが書いた回答(追加質問)の文章部分は私の回答の下のコメント欄に書いて、コードの部分は、コメント欄ではインデントが効かないので、質問欄に追記する形で書いてください。 質問者さんが書いた回答は削除願います。
退会済みユーザー

退会済みユーザー

2023/01/13 23:21

話が通じてないです。もう一回書きますのでよく読んでください。 質問者さんが書いた回答(追加質問)の文章部分は私の回答の下のコメント欄に書いて、コードの部分は、コメント欄ではインデントが効かないので、質問欄に追記する形で書いてください。 質問者さんが書いた回答は削除願います。
oikawasouta

2023/01/14 02:24

大変失礼しました。誤ったコメントについては削除依頼中になります。 追記にありように、 頂いた参考例をもとに反映しました。こちら試したところ、スタートボタンを押した一回目だけメモリリークをおこし、(1000回処理だとぎり耐えます)2回目以降はリークを起こさない現象が起きました。理由がわからず困っています。教えていただけたら幸いです。よろしくお願いいたします。 以上よろしくお願いいたします。
退会済みユーザー

退会済みユーザー

2023/01/14 02:58 編集

上の私のコメントで「質問者さんが書いた回答(追加質問)の文章部分は私の回答の下のコメント欄に書いて」とお願いしましたが、それがイヤなら上の質問者さんのコメントの文章の、 頂いた参考例をもとに反映しました。こちら試したところ、スタートボタンを押した一回目だけメモリリークをおこし、(1000回処理だとぎり耐えます)2回目以降はリークを起こさない現象が起きました。理由がわからず困っています。 ・・・を上の質問欄の「追記  SurferOnWwwさんのサンプルプログラム反映後」の行の直下に追記してください。 ここ質問のコメント欄は、もともと質問内容への情報の追加等を依頼する場所で、情報の追加を行う場所ではありません。初期画面では閉じているので読まない人も多々いますし。
退会済みユーザー

退会済みユーザー

2023/01/14 02:59

> 頂いた参考例をもとに反映しました。こちら試したところ、スタートボタンを押した一回目だけメモリリークをおこし、(1000回処理だとぎり耐えます)2回目以降はリークを起こさない現象が起きました。理由がわからず困っています。 それに対するレスは私の回答欄に追記しておきます。
退会済みユーザー

退会済みユーザー

2023/01/15 22:28

質問者さん、その後無言ですが、追加質問に対しても回答したのでそれに対するフィードバックを返してください。役に立った/立たなかったぐらいはすぐに返せるのでは? 役に立たなかったならどこがダメかを書くとより期待に近い回答が出てくるかも。解決したなら解決に役立った回答にベストアンサーをつけてクローズしてください。とにかく無言は NG です。
oikawasouta

2023/02/15 12:52

お返事遅れて大変申し訳ございません。 usingステートメントを使用してアンマネージドリソースを開放する必要があるという件に関しては非常にためになりました。しかし、pictureBoxに二値化後の画像を表示したいのですが、usingステートメントで 開放してしまうためかエラーが発生するため解決はしていない段階になります。
guest

回答3

0

回答ではありません

誰でも似たような現象を起こせる、再現しやすいコード(の対策版)を書いてみました。

作成環境

  • Microsoft Windows 10
  • Microsoft Visual Studio Community 2019

再現環境

作成手順

※Visual Studio 2019での作成手順です

  1. Windowsフォームアプリでプロジェクトを作成
  2. PerformanceTestAppというプロジェクト名に設定して「次へ」
  3. .NET5.0(サポート対象外)を選択して「作成」
  4. PerformanceTestAppプロジェクトを右クリックして「NuGetパッケージの管理」
  5. 「参照」タブで以下のパッケージをインストール
  6. Form1.csをPerformaceTestForm.csにリネームして「はい」
  7. ソリューションエクスプローラーからPerformanceTestForm.csを右クリックしてコード表示して全部消して下記コードをコピペ
  8. ソリューションエクスプローラーからPerformanceTestForm.Designer.csを表示して全部消して下記コードをコピペ
  9. ソリューションエクスプローラーからPerformanceTestForm.csを右クリックしてデザイナーで表示して、ボタンを選択した状態からImageプロパティを書き換えようとしてダイアログを開き、Local resourceのImportから下記URLからダウンロードした画像ファイルを選択してOK。
  10. 全て保存してビルド

NuGetで追加するパッケージ

・OpenCvSharp4(4.6.0.20220608)
・OpenCvSharp4.Extensions(4.6.0.20220608)
・OpenCvSharp4.Windows(4.6.0.20220608)

画像URL

https://unsplash.com/ja/%E5%86%99%E7%9C%9F/tfjKJ_gN39E
(UnsplashDan Waymanさんが撮影した写真)
※オリジナルサイズの画像を使ってください

コード

PerformanceTestForm.cs

cs

1using OpenCvSharp; 2using OpenCvSharp.Extensions; 3using System; 4using System.Diagnostics; 5using System.Drawing; 6using System.Threading.Tasks; 7using System.Windows.Forms; 8namespace PerformanceTestApp 9{ 10 public partial class PerformanceTestForm : Form 11 { 12 private Mat image = null; 13 private Stopwatch sw = new Stopwatch(); 14 public PerformanceTestForm() 15 { 16 InitializeComponent(); 17 } 18 private async void buttonStart_Click(object sender, EventArgs e) 19 { 20 buttonStart.Enabled = false; 21 var pic = new Bitmap(pictureBox.Image); 22 await Task.Run(() => 23 { 24 if (image == null) image = BitmapConverter.ToMat(pic); 25 sw.Restart(); 26 for (int i = 0; i < 1000; i++) 27 { 28 using var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); 29 using var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); 30 pic?.Dispose(); 31 pic = BitmapConverter.ToBitmap(thresholdImege); 32 } 33 sw.Stop(); 34 }); 35 var oldImage = pictureBox.Image; 36 pictureBox.Image = pic; 37 oldImage?.Dispose(); 38 MessageBox.Show("時間: " + sw.Elapsed); 39 buttonStart.Enabled = true; 40 } 41 } 42}

PerformanceTestForm.Designer.cs

cs

1 2namespace PerformanceTestApp 3{ 4 partial class PerformanceTestForm 5 { 6 /// <summary> 7 /// Required designer variable. 8 /// </summary> 9 private System.ComponentModel.IContainer components = null; 10 11 /// <summary> 12 /// Clean up any resources being used. 13 /// </summary> 14 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 15 protected override void Dispose(bool disposing) 16 { 17 if (disposing && (components != null)) 18 { 19 components.Dispose(); 20 } 21 base.Dispose(disposing); 22 } 23 24 #region Windows Form Designer generated code 25 26 /// <summary> 27 /// Required method for Designer support - do not modify 28 /// the contents of this method with the code editor. 29 /// </summary> 30 private void InitializeComponent() 31 { 32 this.pictureBox = new System.Windows.Forms.PictureBox(); 33 this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); 34 this.buttonStart = new System.Windows.Forms.Button(); 35 ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); 36 this.tableLayoutPanel.SuspendLayout(); 37 this.SuspendLayout(); 38 // 39 // pictureBox 40 // 41 this.pictureBox.Dock = System.Windows.Forms.DockStyle.Fill; 42 this.pictureBox.ImageLocation = ""; 43 this.pictureBox.Location = new System.Drawing.Point(3, 3); 44 this.pictureBox.Name = "pictureBox"; 45 this.pictureBox.Size = new System.Drawing.Size(510, 343); 46 this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 47 this.pictureBox.TabIndex = 0; 48 this.pictureBox.TabStop = false; 49 // 50 // tableLayoutPanel 51 // 52 this.tableLayoutPanel.ColumnCount = 1; 53 this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); 54 this.tableLayoutPanel.Controls.Add(this.pictureBox, 0, 0); 55 this.tableLayoutPanel.Controls.Add(this.buttonStart, 0, 1); 56 this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; 57 this.tableLayoutPanel.Location = new System.Drawing.Point(0, 0); 58 this.tableLayoutPanel.Name = "tableLayoutPanel"; 59 this.tableLayoutPanel.RowCount = 2; 60 this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); 61 this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 62 this.tableLayoutPanel.Size = new System.Drawing.Size(516, 399); 63 this.tableLayoutPanel.TabIndex = 2; 64 // 65 // buttonStart 66 // 67 this.buttonStart.Dock = System.Windows.Forms.DockStyle.Fill; 68 this.buttonStart.Location = new System.Drawing.Point(3, 352); 69 this.buttonStart.Name = "buttonStart"; 70 this.buttonStart.Size = new System.Drawing.Size(510, 44); 71 this.buttonStart.TabIndex = 1; 72 this.buttonStart.Text = "START(&S)"; 73 this.buttonStart.UseVisualStyleBackColor = true; 74 this.buttonStart.Click += new System.EventHandler(this.buttonStart_Click); 75 // 76 // PerformanceTestForm 77 // 78 this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 79 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 80 this.ClientSize = new System.Drawing.Size(516, 399); 81 this.Controls.Add(this.tableLayoutPanel); 82 this.Name = "PerformanceTestForm"; 83 this.Text = "PerformanceTest"; 84 ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); 85 this.tableLayoutPanel.ResumeLayout(false); 86 this.ResumeLayout(false); 87 88 } 89 90 #endregion 91 92 private System.Windows.Forms.PictureBox pictureBox; 93 private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; 94 private System.Windows.Forms.Button buttonStart; 95 } 96}

x86の32bit/64bitプラットフォームの追加

  1. ツールバーでAny CPUとなっているところから構成マネージャーを選ぶ
  2. プラットフォームで、新規作成(x86)を選ぶ
  3. 同様にx64も作成
  4. あとはツールバーからAny CPU/x86(32bit)/x64(64bit)を自由に選択できる

※今回の現象(エラー)は32bitでしか出ません

再現手順

再現コードと言う割に、リソースリークを起こさない形になっているので、usingを取っ払ったり、Disposeを取っ払ってビルドして32bitで実行すれば再現します。

cs

1... 2 /* using */ var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); 3 /* using */ var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); 4 //pic?.Dispose(); 5...

注意事項

連続して実行すると二値化後の画像を再使用しちゃうので、測定の意味がありません。

最後に

コメントや編集を追うのが面倒になったので、調べたときに書いたコードを手順付きで貼っただけです。
回答ではありません。

投稿2023/01/14 01:52

編集2023/01/14 02:35
dameo

総合スコア943

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

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

0

ベストアンサー

ループ内で使用しているgrayImagethresholdImegepicを全て解放しましょう。

投稿2023/01/11 22:30

YAmaGNZ

総合スコア10258

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

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

0

YAmaGNZ さんが回答で言われている「ループ内で使用しているgrayImage、thresholdImege、picを全て解放」するための using 句の使い方のサンプルを書いておきます。質問者さんのコードに適用して問題ないことが確認出来たら YAmaGNZ さんの回答にベストアンサーをつけてください。

C#

1using OpenCvSharp; 2using System; 3using System.Diagnostics; 4using OpenCvSharp.Extensions; 5 6namespace ConsoleAppOpenCV 7{ 8 internal class Program 9 { 10 static void Main(string[] args) 11 { 12 // 239KB の jpeg ファイル 13 var file = @"C:\Users\surfe\Documents\Visual Studio 2022\CsProject\ConsoleAppOpenCV\ConsoleAppOpenCV\911GT2.jpg"; 14 Mat image = Cv2.ImRead(file); 15 16 Stopwatch sw = new Stopwatch(); 17 sw.Start(); 18 19 for (int i = 0; i < 1000; i++) 20 { 21 using (var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY)) 22 using (var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary)) 23 using (var pic = BitmapConverter.ToBitmap(thresholdImege)) 24 { 25 if (i % 100 == 0) 26 { 27 Console.WriteLine($"i: {i}, Time Ealasped: {sw.Elapsed}"); 28 } 29 } 30 } 31 32 sw.Stop(); 33 Console.WriteLine($"done, Time Erasped: {sw.Elapsed}"); 34 } 35 } 36}

結果は:

イメージ説明


【追記】

質問のコメント欄の 2023/01/14 11:59 の私のコメントで「それに対するレスは私の回答欄に追記しておきます」と書いた件です。

頂いた参考例をもとに反映しました。こちら試したところ、スタートボタンを押した一回目だけメモリリークをおこし、(1000回処理だとぎり耐えます)2回目以降はリークを起こさない現象が起きました。理由がわからず困っています。

質問者さんが追記した以下のコードでは「ループ内で使用しているgrayImage、thresholdImege、picを全て解放」になっていない、即ち pic が解放されてないからだと思います。

C#

1for (int i=0; i<1000; i++) 2{ 3 //グレー化 4 using (var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY)) 5 //二値化 6 using (var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary)) 7 { 8 pic = BitmapConverter.ToBitmap(thresholdImege); 9 pictureBox1.Image = pic; 10 } 11}

pic も開放する、すなわち以下のようにして試してみてください。

C#

1for (int i=0; i<1000; i++) 2{ 3 //グレー化 4 using (var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY)) 5 //二値化 6 using (var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary)) 7 using (pic = BitmapConverter.ToBitmap(thresholdImege)) 8 { 9 // これはできないのでとりあえずコメントアウト 10 //pictureBox1.Image = pic; 11 } 12}

何度実行してもメモリーリークは起こらないことが確認できるはずです。

だた、質問者さんのオリジナルのコード、追記版のコード、さらに上のように pic も開放するコードのいずれも 1,000 回実行する意味はない(1 回でも結果は同じ)ということは理解されているでしょうか?

投稿2023/01/12 02:59

編集2023/01/14 03:16
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

oikawasouta

2023/02/15 12:49

お世話になっております。回答ありがとうございます。「これはできないのでとりあえずコメントアウト」 とありますが、pictureBoxに表示する処理も繰り返し行いたいのです。 コメントアウトをはずすと「System.ArgumentException: '使用されたパラメーターが有効ではありません。」 というエラーがでるためできないと仰っていますでしょうか?
len_souko

2023/02/16 14:34

質問者さん、僕が質問へのコメント(2023/01/12 02:09)で貼ったリンクは見ていませんよね? 見てたら試したこと①にて55行目に書いてるはずありませんので Disposeの際にBitmapイメージの実メモリを開放してしまうので、まだPictureBoxで使用中だから解放できないとなっているはずです ループで開放すべきはpicではなく1週前のpicが入っている代入前のpictureBox1.Imageです 順番的には古いpicをpictureBox1.Imageから取得する 新しいpicをpictureBox1.Imageに代入する 取得しておいた古いpicをnullでない場合にDisposeする 追加の参照先 https://atsukanrock.hatenablog.com/entry/20110421/1303381271 こちらでは新しいpicを代入前に直接pictureBox1.ImageをDisposeすると例外が発生することがあるとの事
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問