
Ah yes, I miss that. I enable double-buffering and the time improve to
600ms.
Okay.
I made a second version of the tests below which count the frame rates.
On Winform, I get a nice 70 fps while the WPF version is somewhat lower
at 35 fps. What still mysterious is, while the Winform version showing
the nice sequence of rendering work, I cannot see that in the WPF
version. It just show the last rendering sequence when the time is out.
It is maybe due to the different rendering model between the two APIs
(Winform - immediate mode, WPF - retained mode). But, do you have any
idea how to force it to behave like the Winform version. It may becomes
useful in situation where you need to simulate a waveform - for example.
1. Winform
using System;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
namespace MyNamespace
{
public class MyForm : Form
{
private static readonly Pen[] pens = new[] {
Pens.Red,
Pens.Green,
Pens.Blue,
Pens.Cyan,
Pens.Yellow,
Pens.Magenta,
};
private static readonly Random random = new Random();
private const int LINE_WIDTH = 800;
private volatile bool isRendering = true;
private int frameCount = 0;
private Graphics graphics = null;
private BufferedGraphics gfx = null;
public MyForm()
{
Width = LINE_WIDTH;
Height = LINE_WIDTH;
StartPosition = FormStartPosition.CenterScreen;
gfx = BufferedGraphicsManager.Current.Allocate(CreateGraphics(),
new Rectangle(0, 0, LINE_WIDTH, LINE_WIDTH));
graphics = gfx.Graphics;
Shown += (o, e) => TestRenderingSpeed();
}
private void TestRenderingSpeed()
{
Console.Write(String.Format("Run for 10 seconds... "));
new Thread(() =>
{
Thread.Sleep(10000);
isRendering = false;
}).Start();
int totalPens = pens.Length;
while (isRendering)
{
DrawLines(graphics, pens[random.Next(totalPens)],
pens[random.Next(totalPens)]);
gfx.Render();
}
Console.WriteLine(String.Format("Finished.\nFrame count: {0}
Rate: {1} fps", frameCount, frameCount / 10));
}
private void DrawLines(Graphics g, Pen pen1, Pen pen2)
{
g.FillRectangle(Brushes.Black, 0, 0, LINE_WIDTH, LINE_WIDTH);
for (int x = 0; x < LINE_WIDTH; x += 3)
{
g.DrawLine(pen1, x, 0, x, LINE_WIDTH);
}
for (int y = 0; y < LINE_WIDTH; y += 3)
{
g.DrawLine(pen2, 0, y, LINE_WIDTH, y);
}
frameCount++;
}
}
public class MyClass
{
[STAThread]
public static void Main(string[] args)
{
Application.Run(new MyForm());
}
}
}
2. WPF
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using System.Threading;
namespace MyNamespace
{
public class MyWindow : Window
{
private static readonly Pen[] pens = new[] {
new Pen(Brushes.Red, 1.0),
new Pen(Brushes.Green, 1.0),
new Pen(Brushes.Blue, 1.0),
new Pen(Brushes.Cyan, 1.0),
new Pen(Brushes.Yellow, 1.0),
new Pen(Brushes.Magenta, 1.0),
};
private static readonly Random random = new Random();
private MyDrawing drawing;
private const int LINE_WIDTH = 800;
private volatile bool isRendering = true;
public MyWindow()
{
Width = LINE_WIDTH;
Height = LINE_WIDTH;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
drawing = new MyDrawing(LINE_WIDTH);
Content = drawing;
Loaded += (o, e) => TestRenderingSpeed();
}
private void TestRenderingSpeed()
{
Console.Write(String.Format("Run for 10 seconds... "));
new Thread(() =>
{
Thread.Sleep(10000);
isRendering = false;
}).Start();
int totalPens = pens.Length;
while (isRendering)
{
drawing.DrawLines(pens[random.Next(totalPens)],
pens[random.Next(totalPens)]);
}
Console.WriteLine(String.Format("Finished.\nFrame count: {0}
Rate: {1} fps", drawing.FrameCount, drawing.FrameCount / 10));
}
}
public class MyDrawing : FrameworkElement
{
private DrawingVisual visual;
private readonly int lineWidth;
private int frameCount = 0;
public int FrameCount
{
get { return frameCount; }
}
public MyDrawing(int lineWidth)
{
this.lineWidth = lineWidth;
visual = new DrawingVisual();
}
public void DrawLines(Pen pen1, Pen pen2)
{
using (DrawingContext dc = visual.RenderOpen())
{
for (int x = 0; x < lineWidth; x += 3)
{
dc.DrawLine(pen1, new Point(x, 0), new Point(x, lineWidth));
}
for (int y = 0; y < lineWidth; y += 3)
{
dc.DrawLine(pen2, new Point(0, y), new Point(lineWidth, y));
}
}
frameCount++;
}
protected override int VisualChildrenCount
{
get { return 1; }
}
protected override Visual GetVisualChild(int index)
{
return visual;
}
}
public class MyClass
{
[STAThread]
public static void Main(string[] args)
{
Application app = new Application();
app.Run(new MyWindow());
}
}
}