在不同的图形中多次/恢复状态是否安全?

时间:2015-01-24 18:17:35

标签: c# .net system.drawing

将一个Graphics对象的已保存状态与其他Graphics对象一起使用是否安全?例如,如下例所示。

Graphics g1 = ..;
Graphics g2 = ..;

GraphicsState state1 = g1.Save();
g2.Restore(state1); // state from the other Graphics

此外,多次恢复同一状态是否安全?

Graphics g1 = ..;
Graphics g2 = ..;

GraphicsState state1 = g1.Save();
g2.Restore(state1);
g1.Restore(state1); // the same state used second time

我个人在我的代码中遇到两种技术都没有问题,但我想确保它们是安全/允许的。

1 个答案:

答案 0 :(得分:2)

我非常怀疑这是安全的。正如Graphics.Restore()文档所解释的,当您调用Save()时,当前状态被推送到堆栈(而不是 堆栈......只是一些堆栈),然后当您调用{ {1}},状态从堆栈中删除并应用于Restore()实例。

两个Graphics实例共享相同的堆栈是值得怀疑的。从另一个Graphics实例的堆栈中恢复一个Graphics实例的状态是个好主意,这一点同样值得怀疑。

该文档清楚地表明,预期用途是为了平衡GraphicsSave()次调用,并将它们应用于同一个Restore()实例。


修改

为了完整起见,我继续前进并仔细观察,事实上,当程序可能会立即失败时,恢复从另一个Graphics实例保存的状态肯定不是正确的用法: / p>

  • 在托管代码中,文档引用的“堆栈”实际上是作为链接列表实现的。当您调用Graphics时,在应用要还原的状态对象之后,代码会在堆栈中搜索该对象;在找到它之后,它会处理该对象,以及在该对象之后保存但尚未恢复的所有其他状态对象。

如果找不到相应的对象,它只会发出Restore()条消息。所以这不会导致代码崩溃,但很明显这不是理想的行为。

  • 要实际还原状态,托管代码会调用非托管Debug.Fail()函数。从该调用的已批准OOP包装器的文档(GDI+ Graphics.Restore()函数),引用32位整数“state”参数:“(由之前调用Graphics :: Save方法返回这个图形对象)“[强调我的]。

这当然会使意图更清晰。此外,该文档页面继续详细说明正在维护的状态堆栈以及恢复状态时如何管理它。 GDI +堆栈类似于托管堆栈,以相同的方式实现。和托管堆栈一样,如果恢复状态不是为GdipRestoreGraphics()实例,它将无法在堆栈中找到已保存的状态。