积极答复者
关于使用WindowsFormsApplicationBase实现单例程序的一个问题

问题
-
为了实现程序单例运行,我使用了WindowsFormsApplicationBase,如下:
- C# code
-
public class SingleInstanceManager : WindowsFormsApplicationBase { Form m_Mainapp; public SingleInstanceManager(Form app) { m_Mainapp=app; IsSingleInstance=true; } protected override bool OnStartup(StartupEventArgs eventArgs) { Application.Run(m_Mainapp); return false; } protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) { MessageBox.Show("已运行"); } }
现在我在两个需要单例运行的程序中使用这个SingleInstanceManager
A程序:
MainFormA forma=new MainFormA();
SingleInstanceManager manager=new SingleInstanceManager(forma);
manager.Run(null);
B程序:
MainFormB forma=new MainFormB();
SingleInstanceManager manager=new SingleInstanceManager(formb);
manager.Run(null);
现在发现问题:
当只重复运行A程序或B程序时,工作正常。但是,如果启动了一个A程序,再启动B程序,却提示不能再运行。即认为了B程序也是A程序的实例了。但是A程序和B程序是没有任何关系的,请问这个怎么解决?- 已编辑 Mike FengModerator 2012年3月8日 16:41 修改标题
答案
-
Hi 胡玉龙,
你可以通过Activator.CreateInstance方法去反射出来指定dll里的窗体文件,更详细点就是Module Name,同样实现了singleton模式,只要每个窗体的名字都是唯一的。
foreach (Type tCheckType in types)
{
if (tCheckType.IsSubclassOf(typeof(System.Windows.Forms.Form)) && tCheckType.Name == strItem)
{
object o = Activator.CreateInstance(tCheckType);try
{
MethodInfo mi = tCheckType.GetMethod(strEntrance, new Type[] { typeof(object), typeof(object), typeof(object) });
((CModuleForms)p_Apps[strItem]).Form = (System.Windows.Forms.Form)mi.Invoke(o, new Object[] { oParent, oEvent,oWordName });
}
catch (Exception e)
{
}
}
}类似上面的代码。
orichisonic http://blog.csdn.net/orichisonic If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
- 已标记为答案 Mike FengModerator 2012年3月14日 13:39
-
尝试这样做:
public class SingleInstanceManager : WindowsFormsApplicationBase
{
Form sfrm = null; //要启动的那个窗体
static List<Form> m_Mainapps=null; //用于记录已经触发的窗体
static SingleInstanceManager()
{
m_Mainapps=new List<Form>();
}
public SingleInstanceManager(Form app)
{
foreach(Form frm in m_Mainapps)
{
if(frm.GetType().ToString()==app.GetType().ToString()) //说明两个窗体类型一致,表示已经被触发过了
{
IsSingleInstance=false;
break;
}
}
IsSingleInstance=true;
if(IsSingleInstance)
{
sfrm = app;
m_Mainapps.Add(app);
}
}
protected override bool OnStartup(StartupEventArgs eventArgs)
{
if(sfrm!=null)
{
Application.Run(sfrm);
sfrm=null;
return true;
}
else
{
return false;
}
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
MessageBox.Show("已运行");
}
}- 已建议为答案 CrazyGhost_Von 2012年3月8日 15:27
- 已标记为答案 Mike FengModerator 2012年3月14日 13:39
全部回复
-
依我看,我个人认为因为你两个窗体公用一个类SingleInstanceManager,这就导致如果任意一个窗体实例作为参数传入其中,导致IsSingleInstance设置为True,第二个窗体就无法运行了。
【解决方案】
public class SingleInstanceManager : WindowsFormsApplicationBase
{
Form sfrm = null; //要启动的那个窗体
List<Form> m_Mainapps=new List<Form>(); //用于记录已经触发的窗体
public SingleInstanceManager(Form app)
{
foreach(Form frm in m_Mainapps)
{
if(frm.GetType().ToString()==app.GetType().ToString()) //说明两个窗体类型一致,表示已经被触发过了
{
IsSingleInstance=false;
break;
}
}
IsSingleInstance=true;
if(IsSingleInstance)
{
sfrm = app;
m_Mainapps.Add(app);
}
}
protected override bool OnStartup(StartupEventArgs eventArgs)
{
if(sfrm!=null)
{
Application.Run(sfrm);
sfrm=null;
return true;
}
else
{
return false;
}
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
MessageBox.Show("已运行");
}
}
- 已编辑 ThankfulHeartModerator 2012年3月7日 2:47
-
尝试这样做:
public class SingleInstanceManager : WindowsFormsApplicationBase
{
Form sfrm = null; //要启动的那个窗体
static List<Form> m_Mainapps=null; //用于记录已经触发的窗体
static SingleInstanceManager()
{
m_Mainapps=new List<Form>();
}
public SingleInstanceManager(Form app)
{
foreach(Form frm in m_Mainapps)
{
if(frm.GetType().ToString()==app.GetType().ToString()) //说明两个窗体类型一致,表示已经被触发过了
{
IsSingleInstance=false;
break;
}
}
IsSingleInstance=true;
if(IsSingleInstance)
{
sfrm = app;
m_Mainapps.Add(app);
}
}
protected override bool OnStartup(StartupEventArgs eventArgs)
{
if(sfrm!=null)
{
Application.Run(sfrm);
sfrm=null;
return true;
}
else
{
return false;
}
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
MessageBox.Show("已运行");
}
}- 已建议为答案 CrazyGhost_Von 2012年3月8日 15:27
- 已标记为答案 Mike FengModerator 2012年3月14日 13:39
-
Hi 胡玉龙,
你可以通过Activator.CreateInstance方法去反射出来指定dll里的窗体文件,更详细点就是Module Name,同样实现了singleton模式,只要每个窗体的名字都是唯一的。
foreach (Type tCheckType in types)
{
if (tCheckType.IsSubclassOf(typeof(System.Windows.Forms.Form)) && tCheckType.Name == strItem)
{
object o = Activator.CreateInstance(tCheckType);try
{
MethodInfo mi = tCheckType.GetMethod(strEntrance, new Type[] { typeof(object), typeof(object), typeof(object) });
((CModuleForms)p_Apps[strItem]).Form = (System.Windows.Forms.Form)mi.Invoke(o, new Object[] { oParent, oEvent,oWordName });
}
catch (Exception e)
{
}
}
}类似上面的代码。
orichisonic http://blog.csdn.net/orichisonic If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
- 已标记为答案 Mike FengModerator 2012年3月14日 13:39