В следующем фрагменте кода 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();
}
}
Прежде чем мне пришлось вызывать AddRow()
из потока, отличного от пользовательского интерфейса, у меня был прямой вызов UpdateGridView()
, и он работал безупречно. Но теперь AddRow()
больше не гарантируется вызов из потока пользовательского интерфейса, поэтому я заменил прямой вызов на dataGridView1.BeginInvoke()
.
Как только я это сделал, мое приложение на основе формы начало выдавать System.InvalidOperationException
каждые несколько вызовов AddRow()
, прерывая оператор mSqlDataAdapter.Fill(mDataSet);
(!) со следующим сообщением:
Неверная попытка вызвать Read, когда ридер закрыт
Мой вопрос: почему?
- Какой читатель? адаптер данных? SqlConnection? Источник данных DataGridView?
- Я забочусь об окружении
BeginInvoke()
с помощью Open() и Close() mSqlConnection, и я даже открываю mSqlConnection (снова!), если он не открыт, так почему же я получаю эту «закрытую» ошибку? - Как правильно решить эту проблему? (т. е. обновление DataGridView из потока, отличного от пользовательского интерфейса)