Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Рисование в фоновом потоке


Автор: mgukov 10.4.2011, 21:51
Здравствуйте. Задача такая

Моделируется некоторый тех процесс, результат моделирования должен отображаться в виде диаграммы в реальном времени. Диаграмма довольно сложная, поэтому рисование ее в основном потоке невозможно, а как нарисовать ее в фоновом потоке тоже не понятно. Как можно решить данную задачу в WPF?

Возможен ли такой подход - в фоновом потоке создаем объект DrawingVisual, рисуем с помощью него диаграмму, а затем полученную "картинку" каким то образом через Dispetcher.Invoke рисуем на форме?

Автор: under_sun 10.4.2011, 23:05
Что понимается под сложностью диаграммы? Если сложность расчетов, то расчеты проводи в другом потоке, а диаграмму рисуй уже по просчитанным точкам.

Автор: mgukov 10.4.2011, 23:09
Под сложностью понимается главным образом большое число элементов (квадратов) из которых состоит диаграмма

Автор: mgukov 11.4.2011, 00:55
Видимо я использую WPF не по назначению.

Мне нужно визуализировать результат моделирования, а результат моделирования - массив[300, 300] (тепловое поле). Для каждой точки я рисую квадрат, цвет которого зависит от температуры в данной точке. Векторная графика мне не нужна, а вот высокая скорость желательна.

Подскажите чем можно воспользоваться для моей задачи в WPF.

Автор: -Mikle- 11.4.2011, 08:12
Ну можете тогда рисовать в битмапе в отдельном потоке и по окончанию растровую картинку давать основному потоку. Но я что-то сомневаюсь, что 90000 квадратиков долго рисуются. Они могут долго прорисовываться (так как вы рисуете векторно), но сам процесс рисования по идее должен быстро проходить.

Автор: mgukov 11.4.2011, 10:45
Пример
Код

DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();

for(iny i = 0; i < length; ++i) // length = 90000, квадраты размером 2x2 пиксела
{
    dc.DrawRectangle(brush, pen, rect);
}

dc.Close(); // самая долговыполняющаяся часть кода (несколько секунд)



Может быть я что-то не правильно делаю?
А как прорисовывание ускорить, если дело в нем?

Автор: -Mikle- 11.4.2011, 11:41
Само прорисовывание никак, насколько я знаю (может кто-то и поделится, если знает как). Рисуйте в битмапе фоново (DrawingContext из битмапа получите), а потом передадите готовый рисунок для отображения.

Автор: mgukov 11.4.2011, 11:59
А в битмапе рисовать средствами System.Drawing? Или в WPF есть что нибудь для растровой графики?

Автор: -Mikle- 11.4.2011, 13:04
Нет, зачем. Все есть. Вот один из способов.

Код

     DrawingVisual drawingVisual = new DrawingVisual();
     using (DrawingContext drawingContext = drawingVisual.RenderOpen())
     {
         // рисуем
     }

     RenderTargetBitmap bitmap = new RenderTargetBitmap(width, height, dpi, dpi, PixelFormats.Default);
     bitmap.Render(drawingVisual);

     // все, bitmap готов

Автор: under_sun 11.4.2011, 18:09
Ради интереса попробовал у себя. Код drawingContext.Close() выполняется за 250-270 мс.

Код такой:
Код

public void Update ( Color[] colors )
{
     var drawingContext = _visual.RenderOpen();
     int k = 0;
     for ( int i = 0; i < 300; i++ )
     {
          for ( int j = 0; j < 300; j++ )
          {
                var rect = new Rect( new Point( j * 2, i * 2 ), new Size( 2, 2 ) );
                drawingContext.DrawRectangle( new SolidColorBrush( colors[k++] ), null, rect );
          }
      }
      drawingContext.Close();
}


Конечно, может у тебя комп послабже, но все равно разница кажется слишком большой.

Цитата(-Mikle- @ 11.4.2011,  13:04)
Нет, зачем. Все есть. Вот один из способов.

Код

     DrawingVisual drawingVisual = new DrawingVisual();
     using (DrawingContext drawingContext = drawingVisual.RenderOpen())
     {
         // рисуем
     }

     RenderTargetBitmap bitmap = new RenderTargetBitmap(width, height, dpi, dpi, PixelFormats.Default);
     bitmap.Render(drawingVisual);

     // все, bitmap готов

Тут все равно вызывается тот же drawingContext.Close().

Автор: mgukov 11.4.2011, 19:16
Возможно я погорячился, написав несколько секунд
Комп вроде нормальный, но в параллельном потоке еще сама модель работает, и все же скорость у меня получается не удовлетворительная, тоже самое с помощью OpenGL (Tao Framework) рисуется гораздо быстрей.


Спасибо всем за помощь, понял что мне надо почитать литературу, поглубже разобраться с WPF

Автор: -Mikle- 13.4.2011, 06:57
Цитата(under_sun @  11.4.2011,  21:09 Найти цитируемый пост)
Тут все равно вызывается тот же drawingContext.Close().

Ну я не спорю, пример был приведен для рисования в битмапе, чтобы если человеку надо, то он мог в отдельном потоке сделать это.

Цитата(mgukov @  11.4.2011,  00:51 Найти цитируемый пост)
как нарисовать ее в фоновом потоке тоже не понятно

Цитата(mgukov @  11.4.2011,  00:51 Найти цитируемый пост)
Возможен ли такой подход - в фоновом потоке создаем объект DrawingVisual, рисуем с помощью него диаграмму, а затем полученную "картинку" каким то образом через Dispetcher.Invoke рисуем на форме?

Цитата(mgukov @  11.4.2011,  14:59 Найти цитируемый пост)
А в битмапе рисовать средствами System.Drawing? Или в WPF есть что нибудь для растровой графики? 


Вот к этим вопросам был приведен минипример.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)