现在的位置: 首页 > 综合 > 正文

Disposal and Garbage Collection(资源释放处理与垃圾回收)

2012年12月09日 ⁄ 综合 ⁄ 共 4763字 ⁄ 字号 评论关闭

来源地址:http://www.albahari.com/nutshell/cs4ch12.aspx

Calling Dispose from a finalizer(采用完成执行后的释放,也就是析构函数):

class Test : IDisposable
{
public void Dispose() // NOT virtual(非虚函数)
{
Dispose (true);
GC.SuppressFinalize (this); // Prevent finalizer from running.(在执行过程中防止调用最终的资源释放函数)
}

protected virtual void Dispose (bool disposing)
{
if (disposing)
{
// Call Dispose() on other objects owned by this instance(通过其它(类)对象的当前实例调用Dispose() 函数).
// You can reference other finalizable objects here.(你可以在这里引用其它对象的终结方法)
// ...
}

// Release unmanaged resources owned by (just) this object.(在当前的对象(类)中释放其非托管资源)
// ...
}

˜Test()
{
Dispose (false);
}
}

Resurrection - deleting temporary file(采用析构函数的方式激活删除临时文件的方法)

public class TempFileRef
{
public readonly string FilePath;
public TempFileRef (string filePath) { FilePath = filePath; }

~TempFileRef() { File.Delete (FilePath); }
}

Better solution(更好的解决方案):

public class TempFileRef
{
static ConcurrentQueue<TempFileRef> _failedDeletions
= new ConcurrentQueue<TempFileRef>();

public readonly string FilePath;
public Exception DeletionError { get; private set; }

public TempFileRef (string filePath) { FilePath = filePath; }

~TempFileRef()
{
try { File.Delete (FilePath); }
catch (Exception ex)
{
DeletionError = ex;
_failedDeletions.Enqueue (this); // Resurrection
}
}
}

GC.ReRegisterForFinalize(这是垃圾回收(类)对象的一个静态方法)

public class TempFileRef
{
public readonly string FilePath;
int _deleteAttempt;

public TempFileRef (string filePath) { FilePath = filePath; }

~TempFileRef()
{
try { File.Delete (FilePath); }
catch
{
if (_deleteAttempt++ < 3) GC.ReRegisterForFinalize (this);
}
}
}

Managed Memory Leak(托管堆的内在泄漏)

class Host
{
public event EventHandler Click;
}

class Client
{
Host _host;
public Client (Host host)
{
_host = host;
_host.Click += HostClicked;
}

void HostClicked (object sender, EventArgs e) { ... }
}

class Test
{
static Host _host = new Host();

public static void CreateClients()
{
Client[] clients = Enumerable.Range (0, 1000)
.Select (i => new Client (_host))
.ToArray();

// Do something with clients ... (对客户端做一些操作)
}
}

Timers and memory leaks(时间对象与内在的泄漏)

using System.Timers;

class Foo
{
Timer _timer;

Foo()
{
_timer = new System.Timers.Timer { Interval = 1000 };
_timer.Elapsed += tmr_Elapsed;
_timer.Start();
}

void tmr_Elapsed (object sender, ElapsedEventArgs e) { ... }
}
class Foo : IDisposable
{
...
public void Dispose() { _timer.Dispose(); }
}
static void Main()
{
var tmr = new System.Threading.Timer (TimerTick, null, 1000, 1000);
GC.Collect();
System.Threading.Thread.Sleep (10000); // Wait 10 seconds (线程等待10秒)
}

static void TimerTick (object notUsed) { Console.WriteLine ("tick"); }
using (var tmr = new System.Threading.Timer (TimerTick, null, 1000, 1000))
{
GC.Collect();
System.Threading.Thread.Sleep (10000); // Wait 10 seconds
}

Weak references(类型引用:var):

var sb = new StringBuilder ("this is a test");
var weak = new WeakReference (sb);
Console.WriteLine (weak.Target); // This is a test(测试目标对象输出的结果)
var weak = new WeakReference (new StringBuilder ("weak"));
Console.WriteLine (weak.Target); // weak(输出弱类型目标对象)
GC.Collect();
Console.WriteLine (weak.Target); // (nothing)由于上一行代码执行了垃圾回收,这里的资源已经被释放了
class Widget
{
static List<WeakReference> _allWidgets = new List<WeakReference>();

public readonly string Name;

public Widget (string name)
{
Name = name;
_allWidgets.Add (new WeakReference (this));
}

public static void ListAllWidgets()
{
foreach (WeakReference weak in _allWidgets)
{
Widget w = (Widget)weak.Target;
if (w != null) Console.WriteLine (w.Name);
}
}
}

Weak references and events(弱类型引用与其事件)

public class WeakDelegate<TDelegate> where TDelegate : class
{
class MethodTarget
{
public readonly WeakReference Reference;
public readonly MethodInfo Method;

public MethodTarget (Delegate d)
{
Reference = new WeakReference (d.Target);
Method = d.Method;
}
}

List<MethodTarget> _targets = new List<MethodTarget>();

public WeakDelegate()
{
if (!typeof (TDelegate).IsSubclassOf (typeof (Delegate)))
throw new InvalidOperationException
("TDelegate must be a delegate type");
}

public void Combine (TDelegate target)
{
if (target == null) return;

foreach (Delegate d in (target as Delegate).GetInvocationList())
_targets.Add (new MethodTarget (d));
}

public void Remove (TDelegate target)
{
if (target == null) return;
foreach (Delegate d in (target as Delegate).GetInvocationList())
{
MethodTarget mt = _targets.Find (w =>
d.Target.Equals (w.Reference.Target) &&
d.Method.MethodHandle.Equals (w.Method.MethodHandle));

if (mt != null) _targets.Remove (mt);
}
}

public TDelegate Target
{
get
{
var deadRefs = new List<MethodTarget>();
Delegate combinedTarget = null;

foreach (MethodTarget mt in _targets.ToArray())
{
WeakReference target = mt.Reference;
if (target != null && target.IsAlive)
{
var newDelegate = Delegate.CreateDelegate (
typeof (TDelegate), mt.Reference.Target, mt.Method);

combinedTarget = Delegate.Combine (combinedTarget, newDelegate);
}
else
deadRefs.Add (mt);
}

foreach (MethodTarget mt in deadRefs) // Remove dead references
_targets.Remove (mt); // from _targets.(移除一些无效的引用对象)

return combinedTarget as TDelegate;
}
set
{
_targets.Clear();
Combine (value);
}
}
}
public class Foo
{
WeakDelegate<EventHandler> _click = new WeakDelegate<EventHandler>();

public event EventHandler Click
{
add { _click.Combine (value); } remove { _click.Remove (value); }
}

protected virtual void OnClick (EventArgs e)
{
EventHandler target = _click.Target;
if (target != null) target (this, e);
}
}

 

【上篇】
【下篇】

抱歉!评论已关闭.