1

DataGridViewコントロールのSelectionChangedイベントをキャッチしていて、イベントハンドラーがそのタスク(いくつかのコントロールの値の設定など)を完了するのに約1/2秒かかります。UI用語では、それは永遠です。

問題は、DataGridViewのユーザーインターフェイスが選択をすぐに更新しないことです。私が望んでいるのは、ユーザーがクリックするとすぐにDataGridViewで選択の変更を確認し、その後、時間のかかる作業を実行することです。タスク全体を完了するにはまだ1/2秒かかり、その間UIは応答しません。それで問題ありません。少なくとも、ユーザーはすぐにフィードバックを受け取ります。

この動作は、次のコードを新しいForm1クラスに挿入することで確認できます。

    private System.Windows.Forms.DataGridView dataGridView1;

    public Form1()
    {
        InitializeComponent();
        dataGridView1 = new DataGridView();
        dataGridView1.Dock = DockStyle.Fill;
        dataGridView1.Columns.Add("Column0", "Column 0");
        dataGridView1.Rows.Add("Row 0");
        dataGridView1.Rows.Add("Row 1");
        dataGridView1.Rows.Add("Row 2");
        dataGridView1.Rows.Add("Row 3");
        dataGridView1.SelectionChanged += 
            new EventHandler(dataGridView1_SelectionChanged);
        this.Controls.Add(dataGridView1);
    }
    private void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        if (this.Handle != null)
        {
            this.DoSomethingForAWhile();
            // Even BeginInvoke doesn't help
            //this.BeginInvoke((MethodInvoker)this.DoSomethingForAWhile);
        }
    }
    private void DoSomethingForAWhile()
    {
        // Do anything that causes a noticable delay

        DateTime t0 = DateTime.Now;
        while ((DateTime.Now - t0).TotalSeconds < 2)
        {
            // Do nothing
        }
    }

通常はControl.BeginInvokeを使用して、1/2秒のタスクが開始する前にペイントメッセージを処理できるようにします。これはListViewコントロールでは機能しますが、何らかの理由でDataGridViewでは機能しません。

別のスレッドで処理を実行し、Invokeを使用してUI値を設定することもできますが、これは単純なタスクである必要があるものにとっては非常に複雑なようです

確かにもっと良い方法があります。

4

1 に答える 1

0

長時間実行するタスクをBackgroundWorkerに固定し、UIにコールバックして更新するのが適切だと思いますが、DataGridView.Refresh()を呼び出し、BeginInvokeを使用することで、必要な動作を得ることができます。

private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
    dataGridView1.Refresh();
    if (this.Handle != null)
    {
        this.BeginInvoke((MethodInvoker)this.DoSomethingForAWhile);
    }
}

このアプローチでは、UIスレッドをブロックしている長時間実行タスクのに、ペイントメッセージをUIスレッドに貼り付けます。その時点では、DataGridViewがそれ自体をペイントするようにまだ指示されていないと思います。そのため、更新が表示されなかったのはなぜですか。

于 2012-05-23T01:30:03.317 に答える