0

画面に [お待ちください] ボックスが表示されている間、メイン フォームをロックしようとしていますが、機能しません。これが私のジレンマです。

私は2つのフォームを持っています。ユーザーが更新ボタンをクリックして SQL Server のリストをロードするメイン フォームと、リストのロード中に表示される [お待ちください] フォーム。C# を使用している場合、SQL Server スレッドは既定で別のスレッドであり、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 に答える