次のコード スニペットでAddRow()
は、非 UI スレッドから呼び出されます。
public partial class Form1 : Form
{
public delegate void InvokeDelegate();
...
SqlConnection mSqlConnection = new SqlConnection("Data Source=" + Environment.MachineName + "\\SQLEXPRESS; Initial Catalog=orderDB; Integrated Security=TRUE; MultipleActiveResultSets=True;");
DataSet mDataSet = new DataSet();
SqlDataAdapter mSqlDataAdapter = new SqlDataAdapter();
...
private void UpdateGridView()
{
if (mSqlConnection.State == ConnectionState.Closed)
mSqlConnection.Open();
mSqlDataAdapter.SelectCommand = new SqlCommand("SELECT * FROM customerTable", mSqlConnection);
mDataSet.Clear();
mSqlDataAdapter.Fill(mDataSet);
dataGridView1.DataSource = mDataSet.Tables[0];
if (mSqlConnection.State == ConnectionState.Open)
mSqlConnection.Close();
}
public void AddRow(int field1, int field2, int field3)
{
mSqlDataAdapter.InsertCommand = new SqlCommand("INSERT INTO customerTable VALUES(@field1, @field2, @field3)", mSqlConnection);
mSqlDataAdapter.InsertCommand.Parameters.Add("@field1", SqlDbType.Int).Value = field1;
mSqlDataAdapter.InsertCommand.Parameters.Add("@field2", SqlDbType.Int).Value = field2;
mSqlDataAdapter.InsertCommand.Parameters.Add("@field3", SqlDbType.Int).Value = field3;
mSqlConnection.Open();
mSqlDataAdapter.InsertCommand.ExecuteNonQuery();
dataGridView1.BeginInvoke(new InvokeDelegate(UpdateGridView)); // UpdateGridView() won't work from a non-UI thread
mSqlConnection.Close();
}
}
AddRow()
非 UI スレッドから呼び出さなければならない前に、私はUpdateGridView()
直接呼び出されていましたが、問題なく動作していました。しかしAddRow()
、UI スレッドからの呼び出しが保証されなくなったため、直接呼び出しをdataGridView1.BeginInvoke()
.
これを行うとすぐに、フォームベースのアプリケーションがいくつかの呼び出しSystem.InvalidOperationException
ごとにスローを開始し、次のメッセージでステートメント ( ! ) を中断しました。AddRow()
mSqlDataAdapter.Fill(mDataSet);
リーダーが閉じているときに Read を呼び出すのは無効です
私の質問はなぜですか?
- 何のリーダー?DataAdapterの?SqlConnection の? DataGridView のデータ ソース?
BeginInvoke()
mSqlConnection のOpen()とClose()で囲み、mSqlConnection が開いていない場合は (もう一度!) 開いていますが、どうしてこの「閉じた」エラーが表示されるのでしょうか?- この問題を解決する正しい方法は何ですか? (つまり、非 UI スレッドから DataGridView を更新する)