我的Wait Dialog应该实现Singleton模式吗?

时间:2010-11-14 12:43:08

标签: c# winforms singleton backgroundworker

我目前正致力于我的个人等待对话实施,它支持任务进度更新和任务取消。 ATM就像这样:

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,否则为连续) ),取消任务的可能性(根据WorkerSupportsCancellation prop)等。方法如下:

    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类结束通常会处理更多而不是BackGroundWorker在其生命周期中?

令我惊讶的是,每次我在调用ShowDialog(Form,BackGroundWorker)时传递一个新的BackGroundWorker,我都能(并且我会)修改WaitDialog的单实例属性。 根据模式,这是正确的行为吗?我可以采取其他途径来实现更好的实施吗?我对任何建议持开放态度。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

不,这不是一个坏主意。 Form类被设计为一次性类。一旦处理了一个表单对象,它就会死机,无法恢复。当您尝试再次显示它时,您将收到ObjectDisposedException。为了防止这种情况,您必须拦截FormClosing事件并停止默认处理。你可以调用Hide()并设置e.Cancel = true。但是现在当你真的想要摆脱它时,你已经有了杀死它的麻烦。

但也许更令人信服的是,您应该只缓存创建成本非常高的对象,但不要占用大量资源。 Form类正好相反。创建它很便宜但是需要非常大量的托管和非托管资源。特别是后者,窗口是一个非常昂贵的OS对象。它可能看起来就像一个Form创建起来很昂贵,但你看到的是在绘制表单上烧掉的周期。当您显示隐藏的表单时,您将刻录完全相同的周期数。