这个太疯狂了。我只画了几千条线OnPaint
处理程序。没有问题,当pen.Width <= 1
,或者当屏幕上没有很多行时。
好的,我画了一张比例尺地图。线宽随地图缩放。当我缩放一些地图时,我得到OutOfMemoryException
. WHY?!
当我设置pen.Width
到 1 - 没问题。当我将其设置为对应的轨道宽度时 - 有些地图绘制正常,有些地图在某些缩放级别抛出异常。
这是怎么回事?它与实际内存使用情况无关。我已经仔细检查过这一点。
顺便说一句,pen.Width
当它发生时我设置为2左右。
代码看起来像foreach (...) g.DrawLine(...)
- 绘制数百行后它崩溃了。
如果我找不到解决方案,我将不得不放弃线宽缩放,这会大大降低演示质量。或者我可以做一个丑陋的黑客尝试捕获这个异常(如果可以捕获的话)......
注意:我不使用任何位图。我不对巨大的数组进行操作。我在绘图期间不打开任何文件。有一个向量数组(大约 10k 个元素),我只是将它们全部绘制为单独的线,对各种地图对象使用不同的笔。当我不碰触的时候pen.Width
- 没有发生异常。当我设置 pen.Width - 某些地图在所有缩放级别下都能正确显示,但有些地图会抛出异常。这 5 支笔是在OnPaint
进入绘图循环之前发生的事件,并在退出循环后正确处理。在绘制每条线之前,先设置其宽度。
我尝试将线坐标限制为仅在视口中实际可见的线坐标。这是多余的,因为Graphics
对象自己处理它。当然这没有帮助。我在一些较小的窗口尺寸上尝试过 - 没有帮助。我尝试打开和关闭双缓冲。没有喜悦。我没主意了。
EDIT:
private void DrawMap(PaintEventArgs e) {
var pens = new[] {
new Pen(TrackColor),
new Pen(SwitchColor),
new Pen(RoadColor),
new Pen(RiverColor),
new Pen(CrossColor)
};
var b = Splines.Bounds;
var g = e.Graphics;
var f = true; // OutFull;
var tr = GetTransformation();
float ts = tr[0], tx = tr[1], ty = tr[2];
TrackSpline[] visible = !f ? Splines.GetSubset(ts, _Viewport) : null;
var ct = f ? Splines.Count : visible.Length;
for (int i = 0; i < ct; i++) {
TrackSpline s = f ? Splines[i] : visible[i];
var pen = pens[s.T];
pen.Width = ts * s.W;
if (ts < 0.01 || s.L) {
var p1 = new PointF(s.A.X * ts + tx, s.A.Y * ts + ty);
var p2 = new PointF(s.D.X * ts + tx, s.D.Y * ts + ty);
g.DrawLine(pen, p1, p2);
} else {
var p1 = new PointF(s.A.X * ts + tx, s.A.Y * ts + ty);
var p2 = new PointF(s.B.X * ts + tx, s.B.Y * ts + ty);
var p3 = new PointF(s.C.X * ts + tx, s.C.Y * ts + ty);
var p4 = new PointF(s.D.X * ts + tx, s.D.Y * ts + ty);
try {
g.DrawBezier(pen, p1, p2, p3, p4);
} catch (OutOfMemoryException) {
g.DrawLine(pen, p1, p4);
}
}
}
foreach (var p in pens) p.Dispose();
}
看到这里丑陋的黑客了吗?它工作完美,我什至看不到哪些曲线被直线代替。明显地g.DrawBezier
抛出异常。我不喜欢丑陋的黑客......