Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我的等待对话框应该实现单例模式吗?_C#_Winforms_Singleton_Backgroundworker - Fatal编程技术网

C# 我的等待对话框应该实现单例模式吗?

C# 我的等待对话框应该实现单例模式吗?,c#,winforms,singleton,backgroundworker,C#,Winforms,Singleton,Backgroundworker,我目前正在进行我的个人等待对话框实现,它支持任务进度更新和任务取消。自动取款机类似于: public partial class WaitDialog : Form { WaitDialog() { InitializeComponent(); } public static WaitDialog Instance { get { return WaitDialogCreator.uniqueInstance; }

我目前正在进行我的个人等待对话框实现,它支持任务进度更新和任务取消。自动取款机类似于:

public partial class WaitDialog : Form
{
    WaitDialog()
    {
        InitializeComponent();
    }

    public static WaitDialog Instance
    {
        get { return WaitDialogCreator.uniqueInstance; }
    }

    public DialogResult ShowDialog(Form owner, string message)
    {
        Instance.lblWaitMessage.Text = message;

        return Instance.ShowDialog(owner);
    }

    public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
    {
        ...
    }

    public DialogResult ShowDialog(Form owner, string message, BackgroundWorker worker)
    {
        ...
    }

    private class WaitDialogCreator
    {
        static WaitDialogCreator() { }

        internal static readonly WaitDialog uniqueInstance = new WaitDialog();
    }
}
在我的ShowDialog方法中,我可以传递一个worker对象参数,这样我就可以根据其属性设置一些属性/处理程序,例如,如果报告进度更改,则使用marquee的进度条类型,否则为continuous,根据WorkerSupportsCancellation属性取消任务的可能性,等等。方法如下所示:

    public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
    {
        if (worker == null)
        {
            throw new ArgumentNullException("worker", "A non-null worker must be provided.");
        }
        else
        {
            Instance.btnCancel.Enabled = worker.WorkerSupportsCancellation;

            //This handler close the dialog
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(onWorkerWorkComplete);

            if (worker.WorkerReportsProgress)
            {
                Instance.pbProgress.Style = ProgressBarStyle.Continuous;

                //Update the progress bar
                worker.ProgressChanged += new ProgressChangedEventHandler(onWorkerProgressChanged);
            }

            if (worker.WorkerSupportsCancellation)
            {
                Instance.btnCancel.Click += (sender, e) => { worker.CancelAsync(); };
            }
        }

        return Instance.ShowDialog(owner);
    }
我将通过父窗体上的控制器以以下方式访问“等待”对话框:

    public Controller(Form window)
    {
        this.window = window;
        this.waitDialog = WaitDialog.Instance;
    }

    ...

    public void ShowWaitDialog(BackgroundWorker worker)
    {
        if (worker == null)
        {
            this.ShowWaitDialog();
        }
        else
        {
            window.BeginInvoke((MethodInvoker)delegate() { waitDialog.ShowDialog(window, worker); });
        }
    }
也许这是一个非常不切实际的问题,但这里的问题是:在这种情况下,应用Singleton模式是正确的,还是应该选择正常的实例创建,因为WaitDialog类ends在其生命周期中通常处理的不仅仅是BackGroundWorker

让我好奇的是,每次在调用ShowDialogForm BackGroundWorker时,我都可以并且将修改WaitDialog的单实例属性。 根据模式,这是正确的行为吗?还有其他更好的实现途径吗?我愿意接受任何建议。

我每次都会创建一个新实例


我不使用单例的原因是,除了使用一个特定的等待操作外,表单没有任何意义。当您只想设置一次类的实例,并反复使用该实例及其特定设置时,可以使用单例模式。

不,这是个坏主意。Form类在很大程度上被设计为一个单一用途的类。一旦窗体对象被处置,它就死了,无法恢复。当您再次尝试显示ObjectDisposedException时,将得到它。为了防止这种情况,您必须截获FormClosing事件并停止默认处理。您可以调用Hide并设置e.Cancel=true。但现在你真的很想摆脱它,却又有了杀死它的麻烦


但也许更令人信服的是,您应该只缓存创建成本非常高但不占用大量资源的对象。Form类正好相反。创建它很便宜,但它需要大量托管和非托管资源。尤其是后者,窗口是一个非常昂贵的操作系统对象。它可能看起来像是一个形式是昂贵的创建,但你看到的是循环,是燃烧的绘画形式。当你显示一个隐藏的表单时,你会燃烧相同数量的循环。

这是一个有趣的观点。因此,基本上,创建/显示一次/销毁表单与缓存表单并多次显示/隐藏表单没有太大区别。。。因此,我将为每个后台操作重新创建表单。谢谢