在C#中,如何锁定表单?

时间:2013-03-28 03:06:27

标签: c# sql-server wait freeze

我正在尝试锁定主表单,而屏幕上显示请稍候框,但它无法正常工作。这是我的困境。

我有2个表格。用户单击刷新按钮以加载SQL Server列表的主窗体,以及在加载列表时显示的Please wait窗体。默认情况下,SQL Server线程在使用C#时是一个单独的线程,它会锁定主线程以处理SQL请求。

我可以添加后台工作程序,但是我无法更新我的组合框以将列表显示为其UI控件。如果我使用处理程序,请等待框的show_dialog()将停止锁定主窗体。

如果在主线程再次激活后没有运行左键单击队列,那么甚至可以锁定此表单?我添加了用户等待时需要执行的代码。

    public void PullServers()
    {
        bool ServersFound = false;
        foreach (string Value in SQL.LocateSqlInstances())
        {
            this.cmbServer.Items.Add(Value);
            ServersFound = true;
        }

        if (!ServersFound)
        {
            this.cmbServer.Items.Add(Strings.Lang("ddServerNoneFound"));
            this.cmbServer.SelectedIndex = 0;
        }
        else
        {
            if (!s.empty(General.setting("SQLSERVER")))
            {
                this.cmbServer.Text = General.setting("SQLSERVER");
            }
            else
            {
                this.cmbServer.SelectedIndex = 0;
            }
        }

        this.picRefreshServers.Image = Properties.Resources.Refresh;
    }

    public static Array LocateSqlInstances()
    {
        using (DataTable sqlSources = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources())
        {
            string Servers = null;
            foreach (DataRow source in sqlSources.Rows)
            {
                string instanceName = source["InstanceName"].ToString();

                if (!s.empty(instanceName))
                {
                    Servers += source["ServerName"].ToString() + "\\" + instanceName + "[[SERVBREAK]]";
                }
            }

            string[] ServersList = Servers.Split(new string[] { "[[SERVBREAK]]" }, StringSplitOptions.RemoveEmptyEntries);
            return ServersList;
        }
    }

1 个答案:

答案 0 :(得分:0)

我认为你使用BackgroundWorker走在正确的轨道上。我发现以下模式对我有用。

在主表单中,您需要执行以下步骤。

  1. 创建BackgroundWorker以执行长时间运行操作。
  2. 启动BackgroundWorker。
  3. 将等待表格显示为模态对话框。
  4. // Step 1:
    BackgroundWorker bg = new BackgroundWorker()
    bg.DoWork += new DoWorkEventHandler(bg_DoWork);
    bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
    
    // Step 2:
    bg.RunWorkerAsync();
    
    // Step 3:
    waitingForm = new WaitingForm();
    waitingForm.ShowDialog();
    

    如您所知,您无法从bg_DoWork处理程序更新UI,因为它不在UI线程上运行。因此,只需获取此处所需的数据,然后使用e.Result参数将其传递给bg_RunWorkerCompleted处理程序。

    private void bg_DoWork(object sender, DoWorkEventArgs e)
    {
        Array servers = SQL.LocateSqlInstances();
        e.Result = servers;
    }
    

    bg_RunWorkerCompleted在UI线程上运行,因此可以安全地在此处更新控件。您应该在此处关闭等待表单,然后更新您的UI。

    private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Close the Waiting form.
        waitingForm.Close();
    
        // Retrieve the result of bg_DoWork().
        Array servers = e.Result as Array;
    
        bool ServersFound = false;
        foreach (string Value in servers)
        {
            this.cmbServer.Items.Add(Value);
            ServersFound = true;
        }
    
        if (!ServersFound)
        {
            this.cmbServer.Items.Add(Strings.Lang("ddServerNoneFound"));
            this.cmbServer.SelectedIndex = 0;
        }
        else
        {
            if (!s.empty(General.setting("SQLSERVER")))
            {
                this.cmbServer.Text = General.setting("SQLSERVER");
            }
            else
            {
                this.cmbServer.SelectedIndex = 0;
            }
        }
    
        this.picRefreshServers.Image = Properties.Resources.Refresh;
    }