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

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

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

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

Q&A

解決済

2回答

25046閲覧

c# 画面コントロール生成時の処理速度改善

enenta

総合スコア11

C#

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

0グッド

0クリップ

投稿2017/11/15 06:30

よろしくお願い致します。

###前提・実現したいこと
c#にて、
事前に設定した質問と解答を
dbから取得し動的にコントロールを
配置するシステムを作っています。
コントロール生成に時間がかかってしまい
ここの速度をあげたいです。
現在、100コントロールで3秒程度。
これを1秒程度にしたい。
また、速度アップが無理であれば
他の仕様に変更することも可能。

###発生している問題・エラーメッセージ
画面にはtabcontrolの上に
layoutflowpanelを乗せ
その上にコントロールを追加しています。

追加するコントロールは
その都度dbから取得しています。
基本的には例えば以下のようなコントロールを
追加しています。

氏名 ラベル
氏名解答欄 テキストボックス
生年月日 ラベル
生成月日解答欄 ラジオボタン
(元号 大.昭,平)
テキストボックス3つ
(年、月、日)

ソースとしては以下のような形です
FlowLayoutPanel flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.FlowDirection = FlowDirection.TopDown;
flowPanel.AutoScroll = true;

this.Controls.Add(flowPanel);
※下記は1つのボタンですが
ここはdb内容を見ながら都度
コントロールインスタンス生成を
しながら動的に作成。
下記はプロパティ設定はtextのみだが
実際にはsizeなど
他のプロパティ設定もある。

Button button = new Button();
button.Text = i.ToString();

flowPanel.Controls.Add(button);

###試したこと
速度アップのため、ソースの見直しをしましたが
なかなかうまくいかないため、
マルチスレッド化を検証。

上記ソースにて画面を動的生成するのは
2つ目のタブである。
1つ目のタブに関しては
画面は固定で生成している。

そのため、2つ目の画面生成を
マルチスレッド化して
2つ目画面生成をしている間に
1つ目タブの固定画面に対して
ユーザーからの入力を受け付けようとしたが
マルチスレッド側にて画面生成をしているため
1つ目のタブのテキストボックスなどに
入力ができない(画面が触らない)
※お客様としては、2つ目のタブ画面生成時に
1つ目のタブ画面のコントロールに
入力が出来れば最悪仕様としては良い。

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

言語 c# 2014
画面はlayout flow panelで動的に作成

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

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

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

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

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

guest

回答2

0

現行はこんなようなコードなわけですね。

csharp

1// DBからコントロールの情報を取得? 2// 勝手にDataTableにしていますが適宜読み替えてください 3DataTable dt = /* DBからデータを取得する処理 */ 4 5FlowLayoutPanel flowPanel = new FlowLayoutPanel(); 6flowPanel.Dock = DockStyle.Fill; 7flowPanel.FlowDirection = FlowDirection.TopDown; 8flowPanel.AutoScroll = true; 9 10this.Controls.Add(flowPanel); // ★ 11 12// DBから取得した内容を参照しながら複数のコントロールを生成 13// 勝手にDataTableとDataRowを使っていますが適宜読み替えてください 14foreach (DataRow row in dt.Rows) 15{ 16 Button button = new Button(); 17 button.Text = row[0].ToString(); 18 // button のプロパティを row の情報を参照して適宜変更 19 20 flowPanel.Controls.Add(button); 21}

単なるアイディアで未検証ですが、 の行を諸々のコントロール生成後に持ってきたら、速くなったりしませんか?

csharp

1DataTable dt = /* DBからデータを取得する処理 */ 2 3FlowLayoutPanel flowPanel = new FlowLayoutPanel(); 4flowPanel.Dock = DockStyle.Fill; 5flowPanel.FlowDirection = FlowDirection.TopDown; 6flowPanel.AutoScroll = true; 7 8// this.Controls.Add(flowPanel); // ★ 9 10// DBから取得した内容を参照しながら複数のコントロールを生成 11// 勝手にDataTableとDataRowを使っていますが適宜読み替えてください 12foreach (DataRow row in dt.Rows) 13{ 14 Button button = new Button(); 15 button.Text = row[0].ToString(); 16 // button のプロパティを row の情報を参照して適宜変更 17 18 flowPanel.Controls.Add(button); 19} 20 21this.Controls.Add(flowPanel); // ★

SuspendLayout が入っていても遅いようですと、↑は意味ないかもしれませんね……。

投稿2017/11/15 12:07

alg

総合スコア2019

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

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

alg

2017/11/15 12:19

あるいは `flowPanel.Controls.Add` ではなく `flowPanel.Controls.AddRange` を使う、とか。
enenta

2017/11/15 13:51

ありがとうございます。 ★試して見ます! また、addrangeも試して見ます! あと、少し早くなれば理想の速さまで行きそうです。
guest

0

ベストアンサー

たぶん、追加ごとに描画の計算をしているとかそういうことがパフォーマンスの足を引っ張っているじゃないかな。

大量に追加するときは、計算を止めて、最後に計算させるというのをしないとだめ。

flowPanel.SuspendLayout();

をしています?

普通に作るときに生成される、
InitializeComponent()
を参考にするといいですよ。

あとは、一気に100個のコントロールを見せるのがいけないのであって、
スクロールをすると読み込まれる機構をつくるとか(面倒そう)、
UIとして、カテゴリーごとにわける(簡単!)とかするといいんじゃないですかね。

投稿2017/11/15 09:44

kiichi54321

総合スコア1984

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

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

enenta

2017/11/15 10:03

ご回答ありがとうございます。 flowPanel.SuspendLayout →これはしています。 回答頂きました 描画の計算がいまいち分からないのですが、教えて頂けますでしょうか? また、スクロールやカテゴリごとに分けるアイディアありがとうございます。 現在、タブごとにカテゴリで分けています。お客様からは、タブ1は固定画面、タブ2は動的画面のため、タブ1入力中にタブ2の動的画面(フローレイアウトパネルへのcontrol.add)が作成できないか?と言われています。 僕としては、画面生成時には、画面への入力が出来ないと思っています。
kiichi54321

2017/11/15 11:47

flowPanel.SuspendLayout じゃないとなると、お手上げかな。レイアウト決定のための計算が何度も回ると、遅くなるので、それかな、と思ったのですが。まぁ、あとできることは、処理速度改善は、計測が基本なので、ちゃんと計測することですかね。VSには、色々揃っていますよ。メソッド単位の呼び出し回数の計測とか。VS2014にあるのか、しりませんが。「画面生成時には、画面への入力が出来ない」非同期構文を使えば、原理的にはできると思うのですけどね。 http://ufcpp.net/study/csharp/sp5_async.html
enenta

2017/11/15 13:50

アドバイス頂いた通り InitializeComponentを参考にして見ました。 現在、layoutflowpanelの上に パネルやスプリットコンテナを利用していますので、それに対して、suspendlayoutを指定したところ、劇的に早くなりました。 もう少しソースを見直せば 納品レベルになりそうです。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問