Singleton是一个很平凡的东西,在C++里用多继承去实现是一件很简单的事情,但在C#这样只允许单继承的语言里就没那么简单了。在《Singleton in C#》一文中探讨了常用的几种Singleton实现方式,但这些实现的的缺点很明显——都是侵入式的实现。如果要将某个类作为单件,则必须按照Singleton的实现规范去手工写一次,如果工程中有很多这样的需求那会让我想咬人的。
昨天晚上(中国时间)想到了一个从外部包装的Singleton实现方法,觉得不错,特与大家分享并征讨改进方案。其中的SingletonForm是用于对WinForm实现单体的,这会添加额外的IsLoaded属性支持,在多线程访问UI的时候该属性是很有用的。
using System;
using System.Collections.Generic;
using System.Text;
namespace ymz
{
public static class Singleton<T>
where T : class, new()
{
public static bool IsInstanced
{
get { return instance != null; }
}
public static T Instance
{
get
{
lock (mutex)
{
if (instance == null)
{
instance = new T();
}
return instance;
}
}
}
public static void Release()
{
lock (mutex)
{
instance = null;
}
}
private static object mutex = new object();
private static T instance = null;
}
public static class SingletonForm<T>
where T : System.Windows.Forms.Form, new()
{
public static bool IsInstanced
{
get { return instance != null; }
}
public static bool FormLoaded
{
get { return loaded; }
}
public static T Instance
{
get
{
lock (mutex)
{
if (instance == null)
{
instance = new T();
instance.Load += new EventHandler(instance_Load);
instance.FormClosing += new System.Windows.Forms.FormClosingEventHandler(instance_FormClosing);
}
return instance;
}
}
}
public static void Release()
{
lock (mutex)
{
instance = null;
loaded = false;
}
}
static void instance_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
if (sender != instance)
return;
if (e.CloseReason != System.Windows.Forms.CloseReason.UserClosing)
{
instance.Hide();
e.Cancel = true;
}
}
static void instance_Load(object sender, EventArgs e)
{
if (sender != instance)
return;
loaded = true;
}
private static object mutex = new object();
private static T instance = null;
private static bool loaded = false;
}
}
2007-12-16凌晨
我很要感谢我的SingletonForm,这彻底解决了困扰我多日的UI 死锁问题。WinForm下必须遵守所有的UI控件都必须在UI线程里创建,也都只有通过UI线程才能直接访问。在多线程环境里工作线程在对UI访问时经常会用到对Single<Form>的访问,那这个Form该由谁去创建呢?怎样创建呢?这些都是问题。当Form被UI线程安全的创建后怎样访问就简单了,通过对代理的一个BeginInvoke操作即可将操作任务转交给UI线程去完成。不建议使用Invoke操作,否则可能有deadlock的风险,况且在你操作UI的时候真的有理由让另外一个线程去同步的wait吗?那要多线程作甚?
现在想起来还有点怕,如果死锁这个问题再持续一段时间,那么目前的方案就可能下马,损失可就大了。乞求MS的bug能少一点,那我的日子就能安稳一些。
评论