0

我试图在屏幕上显示请稍候框时锁定主窗体,但它不起作用。这是我的困境。

我有 2 个表格。用户单击刷新按钮以加载 SQL Server 列表的主表单,以及在加载列表时显示的请等待表单。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;
        }
    }
4

1 回答 1

0

我认为您与 BackgroundWorker 走在了正确的轨道上。我发现以下模式对我很有效。

在您的主窗体中,您需要执行以下步骤。

  1. 创建一个 BackgroundWorker 来执行长时间运行的操作。
  2. 启动 BackgroundWorker。
  3. 将等待表单显示为模式对话框。
// 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 线程上运行。因此,只需在此处获取您需要的数据并bg_RunWorkerCompleted使用 e.Result 参数将其传递给处理程序。

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

bg_RunWorkerCompletedUI 线程上运行,因此在这里更新您的控件是安全的。您应该在此处关闭等待表单,然后更新您的 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;
}
于 2013-03-28T15:58:47.363 回答