🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

4691閲覧

vb.netで画像描画を速くしたい。

hanbee.com

総合スコア52

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2021/01/06 12:16

編集2021/01/10 13:30

お世話になっております。私の周りにVB.netを使える人はあまりおらず、ネット検索やこのサイトに助けてもらいながらやっているものです。どうしても、一人では詰んでしまうので、助言やヒントだけでも頂けたらと思っています。
すでに一応完成しているアプリの動作で一度に多数の画像描画を行うイベントがあります。
以下のソースコードのようにして、New句でpictureboxのインスタンスを複数個作っています。
しかし、この動作が少々重く、5秒くらいかかっています。
(レイアウトオブジェクトを生成するコードについては割愛します。)

vb.net

1Public Class tanakakudai 2Private bihin(,) As System.Windows.Forms.PictureBox 3 4Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 5 Me.bihin = New System.Windows.Forms.PictureBox(10, 10) {} 6 Dim img As Image 7 Dim fs As FileStream 8 Dim adress(10, 10) As String 9 'Stopwatchオブジェクトを作成する 10 Dim sw As New System.Diagnostics.Stopwatch() 11 'ストップウォッチを開始する 12 sw.Start() 13 for i = 0 to 10 14 for i = 0 to 10 15 'DBからファイルパスを取得する。 16 adress(i, j) = command.ExecuteScalar() 17 Next 18 Next 19 20 'ストップウォッチを止める 21 sw.Stop() 22 '結果を表示する 23 Console.WriteLine("DBからの読み取り時間は") 24 Console.WriteLine(sw.Elapsed) 25 'ストップウォッチをリセットしてから再開する 26 sw.Reset() 27 sw.Start() 28 29 for i = 0 to 10 30 for i = 0 to 10 31 '取得したファイルパスから描画を行う。 32 Me.bihin(i, j) = New System.Windows.Forms.PictureBox() 33 fs = File.OpenRead(sResult) 34 img = Image.FromStream(fs, False, False) 35 bihin(i, j).Image = img 36 Me.Controls.Add(bihin(i, j)) 37 Next 38 Next 39 'ストップウォッチを止める 40 sw.Stop() 41 '結果を表示する 42 Console.WriteLine("描画にかかる時間は") 43 Console.WriteLine(sw.Elapsed) 44End Class

違う質問で、ある方に、画像を読み込むのではなく、Bitmapクラスを読み込んでクラスメンバとして保持するクラスを用意しておけば、EXE起動時にすべての画像を読み込んでおけば画像の読み込みは一回で済み、ある程度速くなるのではないかとも紹介されています。
その方法をぜひやってみたいと思いますが、クラスメンバに保持するのはどのようにすればよいのでしょうか。
なんとなくイメージはできるのですが、実際に参考になるソースコードが分からず、、困っています。
参考にできるサイトの紹介とかだけでもいいので、宜しくお願い致します。

〇追記
前回の質問の時から、計測をするように回答してくださっていた方、ご忠告に従わず失礼しました。
YAmaGNZさんの回答への返信でも書きましたが、重い腰を上げて計測を行った結果を以下に報告します。

  1. その他レイアウトオブジェクトの生成など: 0.00257s
  2. DBから画像ファイルパスなどの読み出し:0.0129663s
  3. 画像ファイルパスからimageプロパティに変換してpictureboxに描画:0.0069787s
  4. loadイベント全体でかかった時間: 0.0217302s

以上の結果でした。
これは割と性能のいいノートPCで行っているため、処理が速いですが、実際にこのアプリ用に使っている
タブレット端末は中古品で性能も悪く、5秒くらいかかってしまっています。
やはり、Bitmapクラスを読み込んでクラスメンバとして保持するクラスを用意していおいて全ての画像を読み込んでおけば項番2,3の動作が速くなると思います。(DBからファイルパスを持ってきて、imageプロパティに変換するというのを全部EXE起動時にやっておいた方が速くなると思います。)
なので、もっと速くする余地はありそうなので、これらのプログラム修正を行っていきたいと思います。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/01/07 00:05 編集

> 画像を描写する処理しかないので、計測はしていません 前回のアドバイスの内容を全く読んでいない・理解されていないようなので低評価しました
YAmaGNZ

2021/01/10 13:09

どのように計測したのかソースを提示すべきかと思います。
hanbee.com

2021/01/10 13:42

質問文のソースコードを追記致しました。 このようにDBからのファイルパス取得と、Pictureboxへの描画をFor文を分けてそれぞれ計測しています。
YAmaGNZ

2021/01/10 13:48

画像を事前に読み込もうとするのであれば、何かしらの変数に読み込んでおくことになります。 単純に考えればImageの配列とすればいいかと思います。 あとは、その変数のスコープを気にすればよろしいかと
退会済みユーザー

退会済みユーザー

2021/01/10 13:52

>これは割と性能のいいノートPCで行っているため、処理が速いですが、実際にこのアプリ用に使っているタブレット端末は中古品で性能も悪く、5秒くらいかかってしまっています。 速い環境で測っても何も分からないので、実際に使用する遅い環境でログファイルに出力して細かく調査した方がよいかと思います。
hanbee.com

2021/01/10 15:23 編集

YAmaGNZ様、なるほどです。 スタートアップフォームからボタンをクリックすることで、掲示したtanakakudaiのフォームが子フォームとして立ち上がり、画像描画をするアプリになっています。 なので、スタートアップフォームのshownイベントとかででも、全画像ファイルをimage配列に入れておいて、この子フォームが立ち上がった時、LOADイベントでスタートアップフォームのshownで作成したimage配列を描画するピクチャーボックス配列のプロパティに指定したらいいかも、、、というイメージができました。 ただ、一つの懸念点はスコープで、 スタートアップフォームで宣言するimage配列が子フォームで使えるか、、、 public image(,) as image Private Sub startupform1_Shown(sender As Object, e As EventArgs) Handles Me.Shown 'ここでDBからすべてのファイルパスからimage(i,j)に入れる End Sub このようにすればいいですかね。
hanbee.com

2021/01/10 15:21

radian様、 仰る通りだと思いました。計測時間が短すぎて、信頼性がないのですね。 ただ、タブレット端末で調査するのはなかなかハードルが高く、時間もかかるので、 今はとりあえず提案していただいた方法をできるようにしたいと思っています。
guest

回答2

0

ベストアンサー

以前の質問に下記のように書きました。

まずは何の処理に時間がかかっているのか計測して、その処理がLoadイベントで実行しなくてはいけないものなのか、ほかのタイミングで処理できるものなのかを検討すべきです。

今回提示のソースですと、PictureBoxを生成するのに時間がかかっているのか、画像ファイルを読み込むのに時間がかかっているのか、または書かれていない「DBで画像のアドレスを持ってくる」処理に時間がかかっているのか計測すべきです。

そして、その時間のかかっている処理を行うべきタイミングがLoadイベントでしか行えない物なのかを判断すべきです。

もしPictureBoxを生成することに時間がかかっているのであれば、コンストラクタでPictureBoxを生成し、表示タイミングとは違うタイミングでそのフォームのインスタンスを生成することで時間がかかるタイミングが変わり気にならないようになるかもしれません。

また画像を読み込む処理に時間がかかっている場合も同様で、事前に読み込める物なのか判断して事前に読み込めるのであればタイミングをずらすことができるでしょう。
但し、提示されているソースですとその画像が決定される部分は提示されていませんので、事前にその画像が決定されて変わらないものなのか、フォームを開くタイミングで決定されるものなのかの判断もできません。
もしこのタイミングからずらすことができないのであれば、「処理中」といったダイアログを表示してユーザーに待たせるといったことを考えるなどすべきですし、どういうタイミングでも時間が気になるなどであれば時間のかかる処理をアプリケーション起動時に集めて、その間スプラッシュウインドウを表示するなどユーザーをどのようにして待たせるかを考えるのがいいでしょう。

ようは時間のかかる処理によって対応方法がかわってくるということです。
なので、いったい何に時間がかかっているのか計測すべきです。

投稿2021/01/07 00:35

YAmaGNZ

総合スコア10469

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

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

hanbee.com

2021/01/08 08:56

なるほど。画像を表示するのは一つだけの動作かと思っていましたが違うのですね。計測したいと思います。 不慣れなもので時間がかかると思いますが、今からやりたいと思います。ありがとうございます。
hanbee.com

2021/01/08 09:31

実は多くの処理をFor中に入れ込んでおり、本当は「DBから読み出す」、「picture box生成する」、、とfor文全体の中から一つ一つの動作の時間を計測したいですが、どう実現しようか迷っています。 For文の中に sw.start() と入れ込んでも、それは一つの(i,j)に対する計測になってしまいますよね。それに対してなにか方法はありませんでしょうか。自分でもいま考えています。
YAmaGNZ

2021/01/08 14:59

時間を計測するために処理毎にループを別にしてしまうのが楽だと思います。
hanbee.com

2021/01/08 21:54

今までは変数を使いまわしていましたが、それを変える必要があるのですね。承知しました。ありがとうございます。
YAmaGNZ

2021/01/08 22:27

コメントアウトして処理を行わないというのも手です。 目的が時間計測なので、時間計測さえできれば画面が目的の状態にならなくても大丈夫かと思います。
hanbee.com

2021/01/09 03:36

アドバイスありがとうございました。プログラムがすっきりした気がします。 「変数の使いまわし」から、「二次元配列」でのDB読み出しに変更し、各動作でそれぞれFor文を作り、計測しました。 結果は、 1. その他動作(レイアウトに使っているオブジェクトの生成):0.00257s 2. DBから値読み出し:0.0129663s 3. 各々の条件分岐からプロパティを与えて、me.controls.add(・・)するまで:0.0069787s 4. Loadイベント全体でかかった時間:0.0217302s ⇒3のme.controls.addでPictureboxを表示するところで一番時間がかかっているかと思っていましたが、案外DBから読み出すところの方が時間がかかっていることが分かりました。 また、For文の(i,j)で、DBに何も値が入っていないNothingな条件では、if文でContinue For とし、その条件を早々に抜けるというプログラム修正を行いました。 それにより、Loadイベント全体の時間が0.12558s→0.03211sと約4倍速くなるということが分かりました。上での各処理計測はこの修正を追加した上で測定しています。 それにしましても、全体の時間が0.03211sから0.0217303sと、0.01sくらい速くなっているので、これは「変数の使いまわし」から「二次元配列」に構造を見直したことが影響したかなと思います。 ただ、今計測しているのはノートPCですので、実際に使用しているタブレットではもうちょっと遅いです。でも、傾向はつかめているとしたら、 ・Continue Forを使って無駄な条件の処理を早々に抜ける ・DBから読み出した値を格納する方法を「変数の使いまわし」から「二次元配列」にする 上の2点によって、全体の時間を最初に測った時の、0.1255824sから0.0217302sと、(1/5)倍ほどになるかもしれません。 計測を使うことでいろいろ分かることが勉強になりました。ありがとうございます。 ほかにもこの構造を見直したらどうかなど、何か抜けている点があれば教えていただきたいです。
YAmaGNZ

2021/01/09 03:49

5秒くらいかかるという話だったのではないですか? 提示されている時間はすべて1秒以下で問題となる時間とは思えません。
hanbee.com

2021/01/09 04:06

実際にプログラムを使っているタブレット端末は性能が劣るため、5秒くらいかかっています。 まずは、いま分かったことを実際にタブレット端末で試してみて、1秒くらいになるかを確認することにします。そこから、クラスメンバに保持するやり方をする必要があるかを検討したいと思います。
hanbee.com

2021/01/10 02:38

ただ、計測時間は何回かやると違う結果になりますね。。 今やってみたら、項番2のDB読み出しの2倍くらいの時間が項番3の表示にかかる時間でかかりました。 精度的な問題を考えていませんでした。
hanbee.com

2021/01/10 02:47

いまノートPCでやって、0.02秒で完了するLOADイベントに5秒かかってしまっているタブレット端末は、これはプログラム構造いかんよりもタブレット端末の性能の悪さも相当大きいような気もします。
guest

0

質問の直接の回答にはなりませんが、基本的なことを伝えます。
コンストラクタとLoadイベントは前者の方が先に処理されます。
インスタンスが生成されたときに発生する処理がコンストラクタです。
VB.NETでは

Public Sub New()

と書きます。コンストラクタは省略できるのでなくてもエラーになりません。
これに対しLoadイベントは、そのフォームが初めて表示されるときに発生する処理です。
インスタンスを生成してもShow()などで表示しなければLoadイベントは発生しません。

ただ、そのフォームがスタートアップフォームに選択されている場合、インスタンス生成と表示が両方行われるので、
コンストラクタ⇒Loadイベントの順に処理が発生します。

投稿2021/01/07 09:44

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Zuishin

2021/01/07 10:10

質問とまったく無関係のように思いますが、なぜこれを書いたんでしょう?
退会済みユーザー

退会済みユーザー

2021/01/07 10:55

コンストラクタへの理解がないと思ったからですね。前の質問でもNewをよく理解していないと書いてあったし。 コンストラクタは基本的かつ重要な概念ですし、代替案を提示してもここを理解していないまま進めるのは危ういかと。
Zuishin

2021/01/07 11:00

だとしても、理解が進むようなことも、質問の解決の基礎となるようなことも何も書いてありませんが。 この問題でわからなくて困っているのはコンストラクタではなくプロパティ・フィールドだと思います。 もっとも、それらがわかったとしても、実際どこで時間がかかっているかが不明なので根本的に解決方法が違う可能性もあります。まずはそこの調査からだと思います。
hanbee.com

2021/01/09 04:25

コンストラクタという概念はあまり理解しておりません。 sanshimon様の文章とネット検索から勉強して理解したいと思います。 ありがとうございます。
hanbee.com

2021/01/09 04:34

YAmaGNZさんの回答文でもあるように >コンストラクタでPictureBoxを生成し、表示タイミングとは違うタイミングでそのフォームのインスタンス>を生成することで時間がかかるタイミングが変わり気にならないようになるかもしれません。 とありましたが、フォームのインスタンスを作ることとそのフォーム中のオブジェクトを生成するのは分離できるものなのですね。。。? 理解しないといけない概念だと思うので、詳細な説明を調べようと思います。 まず、Public Subというものを使ったことがないので、初歩的なところですが、調べてみます。
Zuishin

2021/01/09 04:48

理解しないといけない概念は山ほどありますが、この質問について言えばコンストラクタで行っても Load で行っても同じでしょうね。
Zuishin

2021/01/09 05:19

どうしてもある程度時間がかかることを容認しなければならないとなったなら、逆に Shown イベントでフォームが表示された後で読み込みを始める方が良いと思います。
Zuishin

2021/01/09 05:58

なお、VB.NET は開発が終了し、これから .NET の進歩に置いていかれることが確定した言語なので、新規に学ぶ意味はほとんどありません。
退会済みユーザー

退会済みユーザー

2021/01/09 06:31

Zuishinさんはどうも人の間違いを指摘するのが目的になっているように見えます。 プログラム言語間には共通の概念が多々ありますので、VB.NETを学ぶのは無駄ではないと言えます。
Zuishin

2021/01/09 06:49

個人攻撃のために VB.NET を推しているんでしょうか? それとも他に目的があって勧めているんでしょうか? 他の言語が選べないのであれば意義もありますね。選べるのであれば C# か F# の方が良いと思います。
Zuishin

2021/01/09 06:51 編集

この回答の意味がわかりませんでしたが、人に回り道をさせるのが目的というなら、納得できます。
退会済みユーザー

退会済みユーザー

2021/01/09 07:16

VB.NETの学習を推奨しているわけではありません。というか言語の話を振ったのはZuishinさんの方であって、私は(というか誰も)そんな話はしてないし、その状態で「VB.NETを勧めている」と推察するのはちょっとおかしいと思いますよ。 まあ将来性を考えればほかの言語の学習もいいかもしれませんね。私からは以上です。
Zuishin

2021/01/09 07:19 編集

VB.NET の将来性に関しては、あなたに言ったわけでもないのに突然絡んできたので何か目的があるのかと思いました。回答の方向性と合致するので、まあそういうことかなと。
vann_2921

2021/01/09 18:42

c#もvb.netも訛りが違うくらいで、.net framework を使う点では何も変わりません。質問者さんは気になさらずにvb.netの勉強をしたらいいと思います。vb.netができればc#もできるようになりますよ。
Zuishin

2021/01/10 11:22 編集

頑張ってそれぞれの訛りを覚えてください。私はどちらも覚えました。 C# を始める際には、他人のソースを参考にする時など、パターンマッチングをはじめとした考え方の違いに戸惑うかもしれませんが、熟練者にとっては何のことはありません。 たとえばうるう年を求める関数は、C# では次のように書くことができます。ちょっと訛りが違うくらいなので、VB を勉強した人なら楽勝で読めますよね? bool IsLeapYear(int year) => (year % 400, year % 100, year % 4) is (0, _, _) or (_, not 0, 0); VB.NET では使えないレコードや null 許容参照型なども便利なのでこれから頻出すると思います。こんな良いものを使わない理由がありません。 あと、個人の意見にすぎませんが、次のように思う人もいるようです。参考にどうぞ。 https://computer-technology.hateblo.jp/entry/20140517/p1 > VBで発信される情報は減ってきている。新しい情報はどれもC#。 http://yamaki.hatenablog.com/entry/20121210/1355126506 >  たとえば、最新のWindowsストアアプリを扱ったセッションや開発レーニングセミナーでは、C#かVisual Basicではなく、C#かJavaScriptを選択するようになっています。
hanbee.com

2021/01/10 02:36

プログラム初心者なものでつい最近(半年前)くらいから.NETを業務改善活動で触りだしました。 自分も次やるときはC#に移行していきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問