为什么Windows在C#中加载时会冻结?

时间:2017-01-21 11:48:29

标签: c# sql

我是C#的新手,我正在使用windows forms。 我正在构建一个应用程序,当Form加载时,我遇到了一个奇怪的严重问题。

我有2 forms

Form1button_EditDataGridView

Form2DataGridView1DataGridView2

正如代码和屏幕截图中显示的那样,当我在Form1中选择一行时,在DataGridView中,然后点击Button_Edit Order number和{{1} } DateTime上的DataGridView中的值传递给Form1,然后Form2打开。 现在在Form2 Form2中有一个Load event查询,需要SQLOrder number来提供相关的订单详细信息,然后填写DateTime和{ {1}}中的{1}}。

screenShot

  • 在Form1中:

    DataGridView1
  • 在Form2中:

    DataGridView2
  • 问题:

此代码可以正常工作,正如我所希望的那样Form2&amp; Form2 frm2 = new Form2(); private void button_Edit_Click(object sender, EventArgs e) { frm2._ Order_Number= Convert.ToInt32(dataGridView1.SelectedRows[0].Cells[0].Value); frm2._ Date_Time= Convert.ToDateTime(dataGridView1.SelectedRows[0].Cells[4].Value); frm2.ShowDialog(); } 中的 SqlConnection MyConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString); SqlCommand MyCommand = new SqlCommand(); DataTable DataTable = new DataTable(); SqlDataAdapter Sql_Data_Adapter = new SqlDataAdapter(); int Order_Number; DateTime Date_Time; int i; double Sum; int RowIndex; public int _ Order_Number { set { Order_Number = value; } } public DateTime _ Date_Time { set { Date_Time = value; } } private void Form2_Load(object sender, EventArgs e) { DataTable.Rows.Clear(); DataTable.Columns.Clear(); MyConnection.Open(); MyCommand.CommandText = "SELECT * FROM Customer_Order_Details WHERE Order_Number = @OrderNumber and Date_Time = @DateTime "; MyCommand.Connection = MyConnection; MyCommand.Parameters.Add("@OrderNumber", SqlDbType.Int).Value = Order_Number; MyCommand.Parameters.Add("@DateTime", SqlDbType.DateTime).Value = Date_Time; Sql_Data_Adapter.SelectCommand = MyCommand; Sql_Data_Adapter.Fill(DataTable); MyCommand.Parameters.Clear(); MyConnection.Close(); dataGridView1.Rows.Clear(); dataGridView2.Rows[0].Cells[1].Value = 0; Sum = 0; //////////////FILL THE ORDER INTO DATAGRIDVIEW1/////////// RowIndex = DataTable.Rows.Count - 1; for (i = 0; i <= RowIndex; i++) { dataGridView1.Rows.Add(DataTable.Rows[i][2], DataTable.Rows[i][3], DataTable.Rows[i][4]); // Calculate the total: Sum = Convert.ToDouble(DataTable.Rows[i][4]) + Sum; } dataGridView2.Rows[0].Cells[1].Value = sum; } 填充了正确的详细信息,并且在DataGridView1加载时工作正常。 但是,在填写DataGridView2和{}之后,有时会Form2冻结加载Form2Form2,在使用任务管理器终止应用程序之前,我无法执行任何操作。 这个问题有时会发生,而且是不可预测的。我真的不知道出了什么问题。

我看了hereherehere,但没有与我的问题相关的问题。请注意,我已经使用了try catch,它不会抛出任何东西,因为表单会冻结。这种冻结行为发生在发布模式中,我的意思是在我构建EXE文件然后我将其安装在PC中,这里出现了问题。

有谁知道为什么会出现这种糟糕的不可预测行为? 我的代码中有什么我应该改变的吗? 我会很高兴听到任何新的想法/解决方案,无论它有多小,它都会非常有益。 谢谢

3 个答案:

答案 0 :(得分:2)

SQL是否适用于另一个线程。检查异步调用。

BeginInvoke

答案 1 :(得分:1)

我建议使用Async Open版本(连接到RDBMS)和ExecuteReader(查询执行):

con.Open()        -> await con.OpenAsync()
q.ExecuteReader() -> await q.ExecuteReaderAsync()

这种简单的替换使得UI 负责(它不会冻结),同时连接到RDBMS并执行查询。

// do not forget to mark Form2_Load method as async 
private async void Form2_Load(object sender, EventArgs e) {
  // Do not share the connection - create it and dispose for each call 
  using (SqlConnection con = new SqlConnection(...)) {
    await con.OpenAsync();

    string sql = 
      @"SELECT * 
          FROM Customer_Order_Details 
         WHERE Order_Number = @OrderNumber 
           AND Date_Time = @DateTime";

    // do not share command/query as well 
    using (SqlCommand q = new SqlCommand(sql, con)) {
      q.Parameters.Add("@OrderNumber", SqlDbType.Int).Value = Order_Number;
      q.Parameters.Add("@DateTime", SqlDbType.DateTime).Value = Date_Time;

      dataGridView1.Rows.Clear();
      dataGridView2.Rows[0].Cells[1].Value = 0;

      Sum = 0;

      // We actually don't want any sql adapter: 
      // all we have to do is to fetach data from cursor and append it to grids
      using (var reader = await q.ExecuteReaderAsync()) {
        while (reader.Read()) {
          dataGridView1.Rows.Add(reader[2], reader[3], reader[4]);
          Sum += Convert.ToDouble(reader[4]);  
        }
      } 
    }  
  }
}

答案 2 :(得分:1)

如上所述,你给我们的代码片段写得不好。您应该使用更多的Try / Catch语句来防止程序崩溃和冻结。这将帮助您在发布时运行Programm时查找错误。此外,您有很多选择来解决您的问题。

1: 尝试在第二个线程中启动Form2,然后只有你的form2将冻结,直到你的sql完成

2: 如前所述,尝试使用异步调用来避免处理sql的冻结时间

3: 没有直接需要SQL数据库/连接。您还可以使用Collection并创建您的Products定义的对象(如cola),然后通过数据库绑定它们。 (如果你有兴趣,我可以给你看一个例子)

最好的方法是:

添加一些Try / Catch语句并熟悉它,熟悉Systems.Thread并尝试在新线程中启动form2,如果这项工作转到第2步并添加asynchronus调用

最后,我想告诉你,那个名字就是你的表格&#34; Form1&#34;和&#34; Form2&#34;不太好,也许你想改变它。