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

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

ただいまの
回答率

91.03%

  • C#

    5749questions

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

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

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 851

circle2017

score 0

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

前提・実現したいこと

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で動的に作成

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

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

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

flowPanel.SuspendLayout();

をしています?

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/15 19:03

    ご回答ありがとうございます。

    flowPanel.SuspendLayout
    →これはしています。

    回答頂きました
    描画の計算がいまいち分からないのですが、教えて頂けますでしょうか?

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

    キャンセル

  • 2017/11/15 20:47

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

    キャンセル

  • 2017/11/15 22:50

    アドバイス頂いた通り
    InitializeComponentを参考にして見ました。

    現在、layoutflowpanelの上に
    パネルやスプリットコンテナを利用していますので、それに対して、suspendlayoutを指定したところ、劇的に早くなりました。

    もう少しソースを見直せば
    納品レベルになりそうです。

    ありがとうございます。

    キャンセル

0

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

// DBからコントロールの情報を取得?
// 勝手にDataTableにしていますが適宜読み替えてください
DataTable dt = /* DBからデータを取得する処理 */

FlowLayoutPanel flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.FlowDirection = FlowDirection.TopDown;
flowPanel.AutoScroll = true;

this.Controls.Add(flowPanel);   // ★

// DBから取得した内容を参照しながら複数のコントロールを生成
// 勝手にDataTableとDataRowを使っていますが適宜読み替えてください
foreach (DataRow row in dt.Rows)
{
    Button button = new Button();
    button.Text = row[0].ToString();
    // button のプロパティを row の情報を参照して適宜変更

    flowPanel.Controls.Add(button);
}

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

DataTable dt = /* DBからデータを取得する処理 */

FlowLayoutPanel flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.FlowDirection = FlowDirection.TopDown;
flowPanel.AutoScroll = true;

// this.Controls.Add(flowPanel);   // ★

// DBから取得した内容を参照しながら複数のコントロールを生成
// 勝手にDataTableとDataRowを使っていますが適宜読み替えてください
foreach (DataRow row in dt.Rows)
{
    Button button = new Button();
    button.Text = row[0].ToString();
    // button のプロパティを row の情報を参照して適宜変更

    flowPanel.Controls.Add(button);
}

this.Controls.Add(flowPanel);   // ★

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/15 21:19

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

    キャンセル

  • 2017/11/15 22:51

    ありがとうございます。

    ★試して見ます!
    また、addrangeも試して見ます!

    あと、少し早くなれば理想の速さまで行きそうです。

    キャンセル

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

  • ただいまの回答率 91.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    5749questions

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