【问题标题】:How to avoid multiple instances of windows form in c#如何避免在c#中出现多个windows窗体实例
【发布时间】:2010-11-27 01:52:48
【问题描述】:

如何避免在c#中出现多个windows窗体实例??我只想运行一个表单实例。因为有机会从我的应用程序的许多页面中打开相同的表单。

【问题讨论】:

    标签: c# singleton


    【解决方案1】:

    实现Singleton pattern

    一个例子:CodeProject: Simple Singleton Forms(好吧,它在 VB.NET 中,但只是给你一个线索)

    【讨论】:

    • 确保重载 FormClosing 并检查关闭原因(如果原因是用户),然后隐藏表单并设置 cancel = true
    • CodeProject 链接已损坏并提供重定向链接为Try Out
    • @Feroz Khan 谢谢。我编辑了我的答案。
    【解决方案2】:

    您可以在打开表单之前检查现有流程:

    using System.Diagnostics;
    
    bool ApplicationAlreadyStarted()
    {
      return Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length == 0;
    }
    

    不知道 GetProcessesByName 方法是否受到 UAC 或其他安全措施的影响。

    【讨论】:

    • 如果您阅读的问题不是关于单例应用程序,而是关于应用程序中的一个表单,该表单可以从许多地方打开并且只需要一个实例。
    【解决方案3】:

    是的,它有单例模式,

    创建单例对象的代码,

    public partial class Form2 : Form
    {
     .....
     private static Form2 inst;
     public static Form2  GetForm
     {
       get
        {
         if (inst == null || inst.IsDisposed)
             inst = new Form2();
         return inst;
         }
     }
     ....
    }
    

    调用/显示此表单,

    Form2.GetForm.Show();
    

    【讨论】:

      【解决方案4】:

      单例不是面向对象的。它们只是全局变量的对象版本。您可以做的是将 Form 类的构造函数设为私有,这样任何人都不会意外创建其中之一。然后在反射中调用,将 ctor 转换为 public 并确保创建一个且只有一个实例。

      【讨论】:

      • 这是个非常糟糕的主意!看看 C# 的“静态类”特性,或者只使用单例模式。
      【解决方案5】:

      如果您的系统有可能为不同的实例数据显示相同类型的表单,那么您可以创建一个检查系统来迭代所有现有的打开表单,寻找唯一的实例数据标识符,然后重新显示任何找到的表单。

      例如具有包含公共属性“CustomerUniqueID”的表单类“CustomerDetails”:

      foreach(Form f in CurrentlyDisplayedForms)
      {
          CustomerDetails details = f as CustomerDetails;
          if((details != null) && (details.CustomerUniqueUD == myCustomerID))
          {
              details.BringToFront();
          }
          else
          {
              CustomerDetails newDetail = new CustomerDetails(myCustomerID);
          }
      }
      

      我们还使用相同的机制来自动强制刷新已编辑和保存客户数据的数据绑定。

      【讨论】:

        【解决方案6】:

        试试这个代码

        Public class MyClass
        {
            //Create a variable named 
            public static int count = 0;
            //Then increment count variable in constructor
            MyClass()
            {
                count++;
            }
        }
        

        在为上述类“MyClass”创建对象时,检查计数值是否大于 1

        class AnotherClass
        {
            public void Event()
            {
                if(ClassName.Count <= 1)
                {
                    ClassName classname=new ClassName();
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          这是我在 ShowForm() 中的解决方案:

              private void ShowForm(Type typeofForm, string sCaption)
              {
                  Form fOpen = GetOpenForm(typeofForm);
                  Form fNew = fOpen;
                  if (fNew == null)
                      fNew = (Form)CreateNewInstanceOfType(typeofForm);
                  else
                      if (fNew.IsDisposed)
                          fNew = (Form)CreateNewInstanceOfType(typeofForm);
          
                  if (fOpen == null)
                  {
                      fNew.Text = sCaption;
                      fNew.ControlBox = true;
                      fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
                      fNew.MaximizeBox = false;
                      fNew.MinimizeBox = false;
                      // for MdiParent
                      //if (f1.MdiParent == null)
                      //    f1.MdiParent = CProject.mFMain;
                      fNew.StartPosition = FormStartPosition.Manual;
                      fNew.Left = 0;
                      fNew.Top = 0;
                      ShowMsg("Ready");
                  }
                  fNew.Show();
                  fNew.Focus();
              }
              private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
              {
                  ShowForm(typeof(FAboutBox), "About");
              }
          
              private Form GetOpenForm(Type typeofForm)
              {
                  FormCollection fc = Application.OpenForms;
                  foreach (Form f1 in fc)
                      if (f1.GetType() == typeofForm)
                          return f1;
          
                  return null;
              }
              private object CreateNewInstanceOfType(Type typeofAny)
              {
                  return Activator.CreateInstance(typeofAny);
              }
          
              public void ShowMsg(string sMsg)
              {
                  lblStatus.Text = sMsg;
                  if (lblStatus.ForeColor != SystemColors.ControlText)
                      lblStatus.ForeColor = SystemColors.ControlText;
              }
          

          【讨论】:

            【解决方案8】:

            当您显示对话框时,只需使用.ShowDialog(); 而不是.Show();

            【讨论】:

            • 非常优雅 :) 我喜欢
            • 仍然存在可以打开多个表单实例的情况,即使使用 ShowDialog 也是如此。例如,从主窗体的菜单,然后从通知图标的上下文菜单。
            【解决方案9】:

            为了让这个表单再次出现在前台,我应用到我的项目中的一个解决方案是:

                private bool checkWindowOpen(string windowName)
                {
                    for (int i = 0; i < Application.OpenForms.Count; i++)
                    {
                        if (Application.OpenForms[i].Name.Equals(windowName))
                        {
                            Application.OpenForms[i].BringToFront();
                            return false;
                        }
                    }
                    return true;
                }
            

            windowName 本质上是您的 Windows 窗体的类名,并且 返回值可用于不创建新的表单实例。

            【讨论】:

            • 好文章。解决了我的问题
            【解决方案10】:

            检查这个link

            using System;
            
            public sealed class Singleton
            {
               private static volatile Singleton instance;
               private static object syncRoot = new Object();
            
               private Singleton() {}
            
               public static Singleton Instance
               {
                  get 
                  {
                     if (instance == null) 
                      {
                        lock (syncRoot) 
                        {
                           if (instance == null) 
                              instance = new Singleton();
                        }
                     }
            
                     return instance;
                  }
               }
            }
            

            【讨论】:

              【解决方案11】:

              这是一个简单的方法。

              检查表单是否为空,或已被处置。如果是这样,我们将创建一个新的表单实例。

              否则我们只显示已经运行的表单。

                  Form form;
                  private void btnDesktop_Click(object sender, EventArgs e)
                  {
                      if (form == null || desktop.IsDisposed)
                      {
                          form = new Form();
                          form.Show();
                      }
                      else
                      {
                          form.WindowState = FormWindowState.Normal;
                      }
                  }
              

              【讨论】:

                【解决方案12】:
                 private static MyForm _myForm;
                    internal static MyForm form
                    {
                        get
                        {
                            if (_myForm == null)
                            {
                                _myForm = new MyForm();
                            }
                            return _myForm;
                        }
                    }
                    public MyForm()
                    {
                        InitializeComponent();
                       _myForm = this;
                    }
                    private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
                    {
                        _myForm = null;
                    }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2020-10-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-01-05
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多