背景
我正在开发一个应用程序,它应该以相同的方式从XP开始在每个Windows平台上运行.通过.NET框架,这在很大程度上非常容易.该应用程序可以在各种触摸表面上运行.该应用程序的目标是.Net 3.0,但如果由于某种原因我应该转移到.Net 3.5,我可以这样做.我无法使用4.0.
该应用程序通过System.Drawing命名空间大量使用GDI.现在,我知道GDI要么根本不是硬件加速,要么只是在极少数的显卡中加速,所以我希望有一些性能问题.但是,这个问题很明显,使应用程序的可用性大大降低.如果可以通过简单的修复避免使用DirectX或OpenGL,我宁愿不重写整个应用程序.
问题
我们最近在其中一个触摸表上安装了Windows 7 64位.这是第一次在Windows 7 64位计算机上运行该应用程序.无论如何,一次在设备上使用多个手指的任何绘图(特别是DrawLine)会导致可笑的滞后量.这种滞后在32位Windows XP或32位Windows 7上并不明显,所以我认为它可能特定于64位Windows 7(我没有要测试的64位XP机器).
由于其中一个.dll文件只有32位库可用于编译,因此该应用程序也被强制作为32位应用程序运行.我在某处读到,在64位系统上强制进程进入32位模式可能会导致性能问题,但是当我升级SDK时我们使用并制作了64位特定的.dll和应用程序,问题仍然存在.
我读到on this other StackOverflow thread,与GDI相关的32位和64位应用程序之间应该没有区别.这似乎不是这种情况.
那么它归结为:你们中的任何人都知道为什么Windows 32位和Windows 64位之间可能会有如此巨大的性能差异吗?如果我找不到解决方案,我将不得不花一点时间让一切都使用硬件加速绘图.如果可能的话,我想避免这种情况.
感谢大家!
编辑:请求的代码段
public delegate void drawLineDelegate(Color color, float width, int x1, int y1, int x2, int y2);
public void drawLine(Color color, float width, int x1, int y1, int x2, int y2)
{
if (InvokeRequired)
{
Invoke(new drawLineDelegate(drawLine), new object[] { color, width, x1, y1, x2, y2 });
}
else
{
try
{
lock (drawLock)
{
pen.Width = width;
pen.Color = color;
scaledPen.Width = width * this.Width / Canvas.Width;
scaledPen.Color = color;
Point p1 = scalePointToScreen(new Point(x1, y1));
Point p2 = scalePointToScreen(new Point(x2, y2));
graphics.DrawLine(pen, x1, y1, x2, y2);
scaledGraphics.DrawLine(scaledPen, p1.X, p1.Y, p2.X, p2.Y);
this.Invalidate(new Rectangle(Math.Min(p1.X, p2.X) - (int)scaledPen.Width, Math.Min(p1.Y, p2.Y) - (int)scaledPen.Width,
Math.Abs(p2.X - p1.X) + 2 * (int)scaledPen.Width, Math.Abs(p2.Y - p1.Y) + 2 * (int)scaledPen.Width));
}
}
catch (Exception ex)
{
if (Scribbler.Properties.Settings.Default.LogLevel >= 2)
{
Scribbler.ScribblerForm.WriteLogMessage(ex.ToString());
}
}
}
编辑:进一步研究
与我们在机器上使用的NVidia卡相比,我做了更多的互联网搜索.这导致我在NVidia开发者论坛上发表了几篇有关同一问题的人的帖子.常见的答案是GDI在Windows 7上被弃用,而较新的NVidia图形驱动程序(从182.5开始)遭受GDI性能问题.解决方案是更新到Direct3D或使用旧驱动程序.有谁知道这是否是最好的行动方案?
最佳答案 我注意到你正在锁定你的绘图代码.你是从多个线程绘制的吗?我怀疑锁定可能与您的性能问题有关.
除非你完全知道自己在做什么,否则不应该从多个线程中绘制.操作系统中有太多关于多线程图形使用的问题.
因为你有一个Invoke,这是一个非常缓慢的过程.你不想一直调用.您永远不应该从后台线程调用此方法.看起来你的锁似乎并不是真的需要,因为你的调用会阻止除消息泵线程以外的任何线程访问.
我认为你将从重新设计你的绘画工作流程中受益匪浅,以确保它被调用一次,并且只能从主消息泵线程中调用.
我也有点困惑为什么你的绘图代码中的区域无效……这可能只是创建一个无限的绘制循环,这也可能是你的问题的一部分.