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値を設定することもできますが、これは単純なタスクである必要があるものにとっては非常に複雑なようです。
確かにもっと良い方法があります。