在以下代码片段中,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 的尝试无效
我的问题是为什么?
- 什么读者?数据适配器的?SqlConnection 的?DataGridView 的数据源?
- 我正在处理
BeginInvoke()
mSqlConnection 的Open()和Close()周围,如果 mSqlConnection 没有打开,我什至会打开它(再次!),那么我为什么会收到这个“关闭”错误? - 解决这个问题的正确方法是什么?(即从非 UI 线程更新 DataGridView)