垃圾回收之避免意外回收
当我们的对象被多个父对象(集合)包含时,我们一定要小心。某一个父对象被回收的话,子实例也将被回收,那些还包含着他的其他父对象的某个记录将是空的或被称为“被释放”。
看以下两个例子,第一个是Windows Form,我写一个控件,他将多次被应用到其他窗口中,所以用全局变量保存他。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public class EditContext
{
Control loginCtl;
static EditContext()
{
current = new EditContext();
}
static EditContext current;
/// <summary>
/// 当前对象
/// </summary>
public static EditContext Current
{
get{return current;}
}
public EditContext()
{
loginCtl = new LoginControl();
}
public Control GetLoginControl()
{
return loginCtl;
}
}
{
Control loginCtl;
static EditContext()
{
current = new EditContext();
}
static EditContext current;
/// <summary>
/// 当前对象
/// </summary>
public static EditContext Current
{
get{return current;}
}
public EditContext()
{
loginCtl = new LoginControl();
}
public Control GetLoginControl()
{
return loginCtl;
}
}
其中的LoginControl是一个用户控件,我将他加入到其他表单里去
Type type = typeof(ParentForm);
object obj = Activator.CreateInstance(type);
IShowLogin show = obj as IShowLogin;
if (show != null)
show.Show(EditContext.Current.GetLoginControl());
object obj = Activator.CreateInstance(type);
IShowLogin show = obj as IShowLogin;
if (show != null)
show.Show(EditContext.Current.GetLoginControl());
表单实现IShowLogin方法
#region IShowLogin 成员
public void Show(Control aControl)
{
this.panel1.Controls.Add(aControl);
this.Show();//ShowDialog的话不会引起错误回收
}
#endregion
public void Show(Control aControl)
{
this.panel1.Controls.Add(aControl);
this.Show();//ShowDialog的话不会引起错误回收
}
#endregion
再来看一个web项目下的代码,他很有趣,或说很麻烦,因为你要找到他有点困难。起码我无法跟你说如何能简单的模拟出来。
同样的,有一个访问太过频繁,我把记录存放在Application里了。而不是每个请求都需要全部数据,于是我设计了这个类
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public class BroadcastContext
{
public static BroadcastContext Current
{
get
{
BroadcastContext obj = HttpContext.Current.Application["BroadcastContext_Current"] as BroadcastContext;
if (obj == null)
{
obj = new BroadcastContext();
HttpContext.Current.Application["BroadcastContext_Current"] = obj;
}
return obj;
}
}
List<MyObject> objs;
public BroadcastContext()
{
objs = new List<MyObject>();
}
public void Add(MyObject obj)
{
{
public static BroadcastContext Current
{
get
{
BroadcastContext obj = HttpContext.Current.Application["BroadcastContext_Current"] as BroadcastContext;
if (obj == null)
{
obj = new BroadcastContext();
HttpContext.Current.Application["BroadcastContext_Current"] = obj;
}
return obj;
}
}
List<MyObject> objs;
public BroadcastContext()
{
objs = new List<MyObject>();
}
public void Add(MyObject obj)
{
if(obj!=null)
objs.Add(obj);
}
public List<MyObject> GetMyBroadcast(int pLastIndex)
{
List<MyObject> retObjs = new List<MyObject>();
foreach (MyObject one in objs)
{
if (one.Index > pLastIndex)//这里one可能是null(被回收了);
retObjs.Add(one);
}
return retObjs;
}
}
}
public List<MyObject> GetMyBroadcast(int pLastIndex)
{
List<MyObject> retObjs = new List<MyObject>();
foreach (MyObject one in objs)
{
if (one.Index > pLastIndex)//这里one可能是null(被回收了);
retObjs.Add(one);
}
return retObjs;
}
}
我们自己开发测试时很难发现上面的代码有问题。但多人同时访问你服务器时,GetMyBroadcast方法就会有麻烦。解决的方法是改变GetMyBroadcast方法,不使用List<MyObject> retObjs,改为返回其他类型。