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

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

ただいまの
回答率

87.58%

WPF の描画速度を改善するには

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 5,551

score 216

Windows 10 Home 64bit、
Visual Studio 2017 Community Edition、
.NET Framework 4.6、WPF + C# で開発しています。

WPF でグラフコントロールを作成してみようと思い、
テスト的に下記のような 3,000 個の点を描画するコントロールを作成しました。

namespace GraphTest
{
    using System;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Media;

    public class GraphControl : FrameworkElement
    {
        private SolidColorBrush _brush;
        private Pen _pen;
        private Random _rand;

        public GraphControl()
        {
            this._brush = new SolidColorBrush(Colors.Orange);
            this._brush.Freeze();

            this._pen = new Pen(this._brush, 1.0);
            this._pen.Freeze();

            this._rand = new Random();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            for (var i = 0; i < 3000; i++)
            {
                drawingContext.DrawEllipse(this._brush, this._pen, new Point((double)this._rand.Next(0, (int)this.RenderSize.Width), (double)this._rand.Next(0, (int)this.RenderSize.Height)), 3.0, 3.0);
            }

            Task.Run(async () =>
            {
                await Task.Delay(1);
                await Dispatcher.BeginInvoke((Action)this.InvalidateVisual);
            });
        }
    }
}

OnRender() の最後に InvalidateVisual() を非同期的に呼び出しているため、
ずっと描画し続けるようになっています。

このとき、
Visual Studio の診断ツールでプロセスメモリを確認すると、
非常に高い頻度で GC がおこなわれていることがわかりました。
そして、おそらくこれが原因で描画速度がかなり遅くなっていました。

OnRender() の中では変なことはしていないつもりなので、
GC が発生する原因は DrawingContext.DrawEllipse() の中にあると思っています。
つまりこの描画方法ではそもそも限界があると認識しています。

しかし、世の中には SciChart など、
非常に高速な描画を実現しているものがあります。
こういったものは一体どのようにして実装しているのでしょうか。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

https://github.com/punio/WpfDrawPerformanceTest
WriteableBitmap をつかうといいみたい。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/27 21:37

    WriteableBitmap を少し触ってみました。
    確かに動作はかなり軽快で感動しました。
    ただ、太さを考慮した点や線を描画するメソッドが標準で用意されておらず、
    現状では WriteableBitmapEx という外部 dll を参照しなければ、
    その部分まで自作しないといけない茨の道になるようです。

    自作のライブラリで描画速度を改善したいため、
    できるだけ外部 dll は使わないようにしたいと思っています。

    要するにもうちょっと楽な方法で実現したいんですが、
    そんな虫のいい話はないんでしょうか…。
    そうじゃないと WriteableBitmapEx に近い、あるいはそのものを
    丸々自作のライブラリに組み込むことになりそうでかなり微妙です。

    キャンセル

  • 2018/08/28 01:32

    最速がWriteableBitmapなだけで、それなら2番手3番手のをつかえばいいんじゃないかな。

    キャンセル

  • 2018/08/28 08:00

    WriteableBitmap 以外の方法も
    サンプルコードで触ってみましたが、
    少しはマシ、という程度で、
    自分にとって十分な性能とはいえませんでした。

    WriteableBitmap(Ex) をもう少し勉強してみようと思います。
    ご回答ありがとうございました。

    キャンセル

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

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

関連した質問

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