- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在我为期两周的解决问题的探索中:
根本问题是垃圾收集器。我的对象的 Finalizer 本来是在对象即将被释放(即回收其资源)时使用react的理想时间。 .NET 垃圾收集系统的问题在于,当 my 终结器被调用时,我拥有的其他对象很可能已经被终结。
如果我与 native 类对象互操作,这个问题就很容易解决。垃圾收集器无法释放我背后的那些对象(并且未经我的许可)。因此,当我的托管对象的终结器被调用时,我知道我的内部状态仍然有效。
我需要的是一种告诉垃圾收集器放开你的手的方法。
有没有办法阻止对象被终结?
例如,下面的代码是错误的,因为终结器错误地将私有(private)的东西 _values
对象仍然存在。实际上,它可能已经在我手下完成:
class Sqm
{
private List<Value> _values = new List<Value>();
//finalizer
public ~Sqm()
{
Shutdown();
}
protected void Shutdown()
{
foreach (var value in _values) //<-- crash; _values no longer exists
SaveValueToHardDrive(value); //<-- crash; value no longer exists
}
}
我需要的是告诉垃圾收集器不要完成该列表对象或其中的任何对象的方法:
class Sqm
{
private List<Value> _values = new List<Value>();
//constructor
public Sqm()
{
GC.LetMeManuallyFinalize(_values);
}
//finalizer
public ~Sqm()
{
Shutdown();
GC.ManuallyFinalize(_values);
}
protected void Shutdown()
{
foreach (var value in _values)
SaveValueToHardDrive(value);
}
}
这有两个可能的问题:
GC.ManuallyFinalize
方法它可能会抑制释放 _values
列出自己,但它引用的对象可能仍会在我的背后完成:
protected void Shutdown()
{
foreach (var value in _values)
SaveValueToHardDrive(value); //<---crash, contained object already finalized
}
所以现在我需要确保添加到列表中的对象也从最终确定中排除:
public void AddSample(String name, Int64 value)
{
Entry entry = GetEntryByName(name);
if (entry == null)
{
entry = new Entry();
GC.LetMeManuallyFinalize(entry);
}
entry.Count += 1;
entry.Sum += value;
entry.Average = entry.Sum / entry.Count;
}
//finalizer
public ~Sqm()
{
foreach (var value in _values)
GC.ManuallyFinalize(value);
GC.ManuallyFinalize(_values);
}
这可能有一个问题,即 Entry
没有其他内部对象,我不知道 List<T>
.垃圾收集器可能会在 _values
上执行不需要的剖腹手术。尽管 _values
本身还没有最终确定。
@MatthewWatson 有个好主意。我认为指出错误的原因会很有用。使用 GCAlloc.Alloc
持有对象的引用。然后您可以在终结器期间使用它来访问它:
public Sqm()
{
private List<Value> _values = new List<Value>();
private GCHandle _valuesHandle; //handle to keep _values alive
//constructor
Sqm()
{
//prevent _values from being finalized
_valuesHandle = GCAlloc.Alloc(_values);
}
//finalizer
~Sqm()
{
try
{
Shutdown(_values); //Safe, right? RIGHT? _values couldn't have been finalized
}
finally
{
_valuesHandle.Free();
}
}
private void Shutdown(List<Values> values)
{
foreach (var value in values)
{
//The list itself might not have been finalized
//But objects used internally to Microsoft's List<T> class have been finalized
//and objects in the list itself were already finalized
SaveValueToHardDrive(value); //<--BAD: values inside list were already finalized
}
}
}
注意:它也可能因为伪记录的行为而失败。来自 The Truth About GCHandles :
When you create a new
GCHandle
, a new entry in the AppDomain's handle table is created. This entry is kept until the handle is freed (viaGCHandle.Free()
) or the AppDomain is unloaded.
强调我的。
原来如此。我需要告诉垃圾收集器
Do not finalize this object (and everything inside it)
棘手的部分是我不拥有的类的内部私有(private)成员;甚至一个对象仍然被 GCAlloc
引用仍然会有它依赖的对象在它背后完成。
public static Foo
{
public static Sqm = new Sqm();
}
Foo.Sqm.AddSample("QueryCustomerInfo", stopwatch.TotalMicroseconds);
最佳答案
无论如何,在终结期间进行任何长期操作(例如输入输出)都是非常糟糕的做法。您应该考虑将对象的 _values 列表存储在静态列表中——这将防止值被破坏。当您的对象正在完成时,您可以将对内部列表的引用保存在另一个定期检查的静态列表中。当它包含对列表的引用时,这意味着您的对象已被破坏并且应该保存它包含的值。
class Sqm
{
private static List<List<Value>> = _lists = new List<List<Value>>();
private static List<List<Value>> = _finalizationQueue = new List<List<Value>>();
private List<Value> _values = new List<Value>();
Sqm() { _lists.Add(_values); }
~Sqm() { _finalizationQueue.Add(_values); }
public static void CheckAndSave()
{
foreach(var list in _finalizationQueue)
SaveValues(list);
}
}
更新:如果域可能在您不希望它关闭时关闭,您唯一的方法是将值存储在另一个域中。
关于c# - 如何阻止对象(以及其中的所有内容)被终结?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18255218/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!