【发布时间】:2016-10-27 04:09:22
【问题描述】:
我制作了一个运行良好的大型应用程序,除了它的 UI(winforms)在使用 webclient 从 Web 检索数据时冻结(链接是嗯...不是最快的),或者从数据库检索查询的数据连接(它存储在一个又远又慢的服务器中——无法避免)。
所以我想利用异步方法,以便用户可以移动、最小化和单击窗口,而不会让操作系统感到紧张并将其标记为“无响应”。
我不希望我的代码在这些冗长的操作之间什么都不做,只是保持 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() 时遇到异常,它说“无法在已经完成的任务中调用 Start”(我正在翻译,我的 VS 不是英文的)。
我在 SO 中检查了一些线程,但老实说,我无法掌握这个概念并将其应用于我的问题,所以我谦虚地寻求帮助。非常感谢!
【问题讨论】:
-
如果你评论那一行?
-
圣洁线程,@Hackerman,就这么简单吗?异常消失了。但话又说回来,UI 在此期间仍然冻结,就像普通的顺序、同步运行一样。
-
你一直在循环直到任务完成,所以你的 UI 仍然会被锁定
-
@ProGrammer - 循环内的
Application.Doevents不应该允许 UI 处理其鼠标单击和布局更改吗? (我有一个选框 ProgressBar 来提供 UI 正在工作的视觉标志)。 -
据我了解,如果它们已经在您的线程被锁定时开始处理,它们将被处理。我不确定在最后一次调用
Application.DoEvents()后触发事件时会受到怎样的影响@
标签: .net vb.net multithreading user-interface asynchronous