这里是否需要GC.KeepAlive,或者我可以依赖本地和参数来保持对象存活吗?

我有一堆方法使用不安全的代码直接使用WPF的WriteableBitmap并从其BackBuffer读取。

每当我做这样的事情时,我是否应该使用GC.KeepAlive并不完全清楚:

 int MyMethod(WriteableBitmap bmp) { return DoUnsafeWork(bmp.BackBuffer); } 

一方面,在MyMethod的堆栈上仍然存在对bmp的引用。 另一方面,它似乎依赖于实现细节 – 这可以编译为尾调用,例如,在输入DoUnsafeWork不保留对bmp的引用。

同样,想象下面的假设代码:

 int MyMethod() { WriteableBitmap bmp1 = getABitmap(); var ptr = bmp.BackBuffer; WriteableBitmap bmp2 = getABitmap(); return DoUnsafeWork(ptr, bmp2); } 

理论上,在方法返回之前,对bmp1的引用仍保留在堆栈中,但同样,它似乎使用了实现细节。 当然编译器可以自由地合并bmp1bmp2因为它们永远不会同时存在,即使编译器从来没有这样做,JITter仍然可以,并且可能确实如此(例如,通过将它们存储在同一个寄存器中,一个,然后另一个)。

所以,一般来说:我应该依赖locals / arguments作为对象的有效引用,还是应该总是使用GC.KeepAlive来保证正确性?

这尤其令人费解,因为显然, FxCop认为GC.KeepAlive总是很糟糕 。

我应该依赖locals / arguments作为对象的有效引用吗?

不,你的分析是正确的; 抖动完全在其权限内告诉垃圾收集器本地的内容在托管代码不再使用的那一刻就已经死了。

我是否应该始终使用GC.KeepAlive来保证正确性?

是。 这就是它的用途。

如果在获取后台缓冲区之前调用了WriteableBitmap.Lock,则应该固定WriteableBitmap并且不会移动底层内存。 至少这是我对WriteableBitmapAPI的解释。

我已经广泛使用了WriteableBitmap,特别是codeplex上的开源WriteableBitmapEx库(披露,我已经为这个库贡献了一次,但它不是我的项目)。 这使用Lock / Access Backbuffer(重复)/ unlock / Invalidate的模式进行绘制。 即使后备缓冲区IntPtr存储在结构中并传递给应用程序,我也从未遇到过这种模式的问题。

最好的祝福,