【问题标题】:Saving to the Database while keeping the UI responsive VB.NET保存到数据库,同时保持 UI 响应 VB.NET
【发布时间】:2015-05-08 16:52:34
【问题描述】:

我有一个按钮,可以使用多种方法将一些 Textboxes 和 Datagridview 内容保存到数据库中,因此整个过程需要很长时间并且 UI 会冻结很多秒,我该如何避免这种情况?也许使用多线程,我已经完成了我的研究,但我仍然无法弄清楚。这是我更好地理解我的代码:

Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click

Dim NbrP As Integer = CInt(combobox1.SelectedIndex)
    Select Case NBR
        Case 0
            Try
                SubmitA(...)
                SubmitB(...)
            MessageBox.Show("Data Inserted")
            Catch ex As Exception
                MessageBox.Show("Error :" & ex.ToString())
            End Try
        Case 1
            Try
                SubmitA(...)
                SubmitB(...)
                SubmitC(...)
                SubmitD(...)
            MessageBox.Show("Data Inserted")
            Catch ex As Exception
                MessageBox.Show("Error :" & ex.ToString())
            End Try
         ..
         ..

    End Select
End Sub

这是 Select Case 中使用的方法之一的示例:

Public Sub SubmitA(ByVal txtSupT As TextBox, ByVal cmbIntP As ComboBox, ByVal lblRecupIdF As Label)
    Dim cmdSau = New MySqlCommand("INSERT INTO sau (sup_totale, nbr_parcelles, ferme_id_ferme) VALUES (@suptot, @nbrparcelles, @fermeid)", db_con)
    Dim cmdRecupIdSau = New MySqlCommand("SELECT id_sau FROM sau WHERE id_sau = ( SELECT MAX(id_sau) FROM sau)", db_con)
    Dim drRecSAU As MySqlDataReader

    cmdSau.Parameters.AddWithValue("@suptot", CDbl(txtSupT.Text))
    cmdSau.Parameters.AddWithValue("@nbrparcelles", CInt(cmbIntP.Text))
    cmdSau.Parameters.AddWithValue("@fermeid", CInt(lblRecupIdF.Text))
    cmdSau.ExecuteNonQuery()

    drRecSAU = cmdRecupIdSau.ExecuteReader()
    While drRecSAU.Read
        recupIdSAU = CInt(drRecSAU(0))
    End While
    drRecSAU.Close()
End Sub

如您所见,如果combobox1值为0,则执行案例一,如果为1,则执行案例二..但是案例二执行案例一方法+其他方法,所以它是偶数更重以保存数据。

我只想在 BtnSave 附近显示一个 CircularProgressBar,同时保持 UI 响应并等待保存整个数据。

提前谢谢你,如果有点不清楚,我很抱歉,我尽量说清楚。

【问题讨论】:

  • 据我所知,没有线程你真的做不到。我发现最简单的方法是使用 BackgroundWorker。在您的情况下,我会将要插入的数据保存(到数组或某种集合中),然后将其传递给后台工作人员。您甚至可以使用 BackgroundWorker 的进度报告功能在流程执行时更新 UI。msdn.microsoft.com/en-us/library/…
  • 我可以建议存储过程。使用 MAX 获取唯一 ID 并不能保证您会收到最后插入的 ID。查看 LAST_INSERT_ID(只要它在同一个事务中),SP 会限制您进行的查询次数。
  • @the_lotus,很好,但现在你引起了我的注意......那个查询的意义何在。即使忽略last_insert_id() 的存在,该查询也可能只是SELECT MAX(id_sau) FROM sau。不需要它是我可以看到的 WHERE 中的子查询。
  • @Uueerdo 我把那个查询弄红得太快了。你是对的,在这种情况下 where 子句是没有用的。
  • 谢谢大家的帮助,你们的回答真的很有帮助,我很感激!如果我以后遇到某种冻结,我仍然想知道是否可以在操作期间使 UI 响应。 (在解决了您提到的问题后,无需更改太多代码并将数据保存到数组或集合中......使用 BGworker)

标签: mysql vb.net multithreading methods freeze


【解决方案1】:

首先弄清楚为什么需要很长时间。你做了很多更新吗?每次更新都需要很长时间吗?

使用 MySQL EXPLAIN 命令查看您的查询实际在做什么。可能存在效率低下的问题,可以通过添加新索引或重组查询来解决。检查不必要的 JOIN 或其他不必要的工作。

例如,在您的帖子中,您有以下查询:

SELECT id_sau FROM sau WHERE id_sau = ( SELECT MAX(id_sau) FROM sau)", db_con)

为什么不只是:

select max(id_sau) from sau

?

为什么要找到最大值...然后在表格中搜索您已经找到的值?

如果您对数据库有许多单独的调用,则可以通过将它们组合到一个调用中来提高性能。将多个 SQL 语句放在一个调用中,或者编写一个 sproc。

如果您对同一条记录进行多次插入,则可以通过进行一次插入多条记录的大插入来提高性能,而不是多次执行相同的插入。 (这方面有很多技术问题,所以这将取决于您要插入多少条记录。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2015-01-11
    • 2019-05-03
    • 2012-07-07
    相关资源
    最近更新 更多