gpt4 book ai didi

.net - 如何使用异步方法加载Db数据并保持UI响应

转载 作者:行者123 更新时间:2023-12-03 12:55:06 25 4
gpt4 key购买 nike

我制作了一个不错的大型应用程序,除了使用Webclient从Web检索数据时链接(winforms)冻结(链接是um ...不是最快的)或从数据库中检索查询的数据连接(储存在较慢的服务器上-无法避免)。

因此,我想到了利用异步方法的优势,以便用户可以移动,最小化和单击窗口,而不会使操作系统感到紧张并将其标记为“不响应”。

我不希望我的代码在这些冗长的操作之间做任何其他事情,只是保持UI响应(我知道我应该禁用控件以防止用户在第一个操作完成之前询问其他问题或同样的问题)。

但是我对异步方法没有任何经验,而我的第一个测试尝试是:

Public Function GetDatatableUIblocked() As DataTable
Dim retTable As New DataTable
Dim connection As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\lanserver\storage\DB.accdb;Persist Security Info=False;")
Dim command = connection.CreateCommand()
command.CommandText = "SELECT * FROM bdPROC;"
connection.Open()
Dim reader = command.ExecuteReader
retTable.Load(reader)
connection.Close()
Return retTable
End Function

Public Function GetDatatableUIfree() As DataTable
Dim retTable As New DataTable
Dim connection As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\lanserver\storage\DB.accdb;Persist Security Info=False;")
Dim command = connection.CreateCommand()
command.CommandText = "SELECT * FROM bdPROC;"
connection.Open()
Dim readerTask = command.ExecuteReaderAsync()

readerTask.Start() '<=========================== EXCEPTION HAPPENS HERE

Do
Application.DoEvents()
Loop Until readerTask.IsCompleted OrElse readerTask.IsFaulted
Dim reader = readerTask.Result
retTable.Load(reader)
connection.Close()
Return retTable
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ProgressBar1.Visible = True
Dim dt = GetDatatableUIblocked()
ProgressBar1.Visible = False
DataGridView1.DataSource = dt
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
ProgressBar1.Visible = True
Dim dt = GetDatatableUIfree()
ProgressBar1.Visible = False
DataGridView1.DataSource = dt
End Sub

但是,在运行 readerTask.Start()时出现异常,它显示类似“无法在已经完成的任务中调用开始”这样的内容(我正在翻译,我的VS不是英语)。

我在SO中检查了一些线程,但老实说,我无法理解这个概念并将其应用于我的问题,所以我谦虚地寻求帮助。非常感谢你!

最佳答案

保持UI自由的一种方法是使用Task。所提出的解决方案通过无所事事的循环来阻止BackGroundWorker的点,以等待其完成。下面的代码进行了其他一些值得注意的更改:

' note the Async modifier
Private Async Sub btnDoIt_Click(...
Dim sql = "SELECT * FROM RandomData"
dtSample = Await Task(Of DataTable).Run(Function() LoadDataTable(sql))
dgv2.DataSource = dtSample
End Sub

Private Function LoadDataTable(sql As String) As DataTable
' NO UI/Control references allowed
Dim dt = New DataTable
Using dbcon As New OleDbConnection(ACEConnStr)
Using cmd As New OleDbCommand(sql, dbcon)
dbcon.Open()
dt.Load(cmd.ExecuteReader())
End Using
End Using
Return dt
End Function

我没有OP中提到的确切条件,但是我确实有一个具有500k行的Access表。这给OleDB造成了沉重的负担,以至于可能需要6到10秒的时间来加载它,足够长的时间来判断UI是否仍然响应。是的
  • 不要忘记在等待Asynch完成的任何方法上使用Task
  • 设置LoadTable方法以从有效查询中加载任何表,以便其他事物可以使用它。如果/当查询更改时,只需对调用它的事物进行更改。
  • 完成后,应处置
  • DB提供程序对象(例如Connections和DBCommand对象)以释放资源并防止泄漏。 Using块为我们做到了。
  • 不需要做任何事情/DoEvents循环,也不需要事件来完成通知。 Await代码将等待load方法完成,以便以后可以执行任何其他操作。
  • Task通常比 BackGroundWorker更易于使用。

    资源
  • Task Class
  • Asynchronous Programming with Async and Await (Visual Basic)
  • Using Statement
  • 关于.net - 如何使用异步方法加载Db数据并保持UI响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38015089/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com