c# - BeginInvoke() 有时会中断 (System.InvalidOperationException),并在阅读器关闭时尝试调用 Read 无效

标签 c# winforms sqldatasource dataadapter begininvoke

在以下代码片段中,从非 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

我的问题是为什么?

  1. 什么读者?数据适配器的? SqlConnection 的? DataGridView 的数据源?
  2. 我正在使用 mSqlConnection 的 Open()Close() 处理 BeginInvoke() 周围的问题,我什至再次打开 mSqlConnection! )如果它没有打开,那么我为什么会收到这个“已关闭”错误?
  3. 解决这个问题的正确方法是什么? (即从非 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/

相关文章:

c# - 压缩 c# dnn 模块设置代码

c# - 将列表转换为带单引号的字符串

c# - MVP 依赖注入(inject)

c# - 如果使用自定义数据源,如何对 ASP.NET GridView 中的列进行排序?

asp.net - 多个DataKeyNames不过滤sqldatasource

c# - 在被调用方法中捕获异常(并忽略),但需要将其抛出调用者中

c# - 如何链接两个希望您提供流的 C# API?

mysql - 如何根据数据库用户信息动态启用/禁用 ToolStripMenuItem?

c# - e.Data.GetDataPresent 在 WinForms 拖放处理程序中不起作用?

asp.net - SqlDataSource动态设置SelectCommand