在以下代码片段中,从非 UI 线程调用 AddRow()
:
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();
}
}
在必须从非 UI 线程调用 AddRow()
之前,我直接调用了 UpdateGridView()
并且它工作完美。但现在不再保证从 UI 线程调用 AddRow()
,因此我用 dataGridView1.BeginInvoke()
替换了直接调用。
一旦我这样做了,我的基于表单的应用程序开始每隔几次 AddRow()
调用抛出一个 System.InvalidOperationException
,从而破坏 mSqlDataAdapter。 Fill(mDataSet);
语句 (!) 包含以下消息:
Invalid attempt to call Read when reader is closed
我的问题是为什么?
- 什么读者?数据适配器的? SqlConnection 的? DataGridView 的数据源?
- 我正在使用 mSqlConnection 的 Open() 和 Close() 处理
BeginInvoke()
周围的问题,我什至再次打开 mSqlConnection! )如果它没有打开,那么我为什么会收到这个“已关闭”错误? - 解决这个问题的正确方法是什么? (即从非 UI 线程更新 DataGridView)
最佳答案
这个问题肯定是由于竞争条件造成的。
从 UpdateGridView 中删除这两行,因为它不是关闭连接的正确位置。
if (mSqlConnection.State == ConnectionState.Open)
mSqlConnection.Close();
使用IAsyncResult检索等待句柄并等待线程完成 GridUpdate。
IAsyncResult Result = dataGridView1.BeginInvoke(new InvokeDelegate(UpdateGridView));
Result.AsyncWaitHandle.WaitOne();
mSqlConnection.Close();
关于c# - BeginInvoke() 有时会中断 (System.InvalidOperationException),并在阅读器关闭时尝试调用 Read 无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13094682/