【发布时间】:2014-11-17 09:24:47
【问题描述】:
我有一个程序,我想在其中使用多线程填充列表视图。
但我有一个问题,即 ui 线程无法足够快地更新列表视图。
当它运行 checkWishList 子时,我得到 listview1.Items.count = 0。
我尝试使用task.waitall(tasks) 处理任务,我尝试使用Task.Factory.ContinueWhenAll,但它也在单独的线程中运行,所以我尝试更新它时出错。
我唯一的工作是
Do Until (tasks(0).Status = 5 And tasks(0).Status = 5)
Application.DoEvents()
Loop
然而,这似乎是一个非常糟糕的解决方案,而不是真正的解决方案。
所以我的问题是,有什么方法可以等待运行 checkWishList() 直到 ui 线程完成更新,或者我可以让 Task.Factory.ContinueWhenAll 在 ui 线程中运行吗?
或者我应该让线程填充 listviewitems 列表,而不是调用 uithread 来添加项目,然后让 listview 连接到该数据源?那会让ui线程更新得更快吗?
或者在列表上运行一个 foreach 并从 ui 线程将它们添加到列表视图中?
将显示大约 30-50 条记录,但搜索这些记录需要时间,所以这就是我希望在多个线程中完成的原因。
当然,我可以在添加 listviewitem 之前先进行 checkWishList DB 查询并立即设置颜色,但是由于我希望其他函数也调用此子函数,这意味着我必须在多个地方使用相同的代码,这使得未来的更新/更改更成问题。
我正在使用 .net 框架 4.5。
Private Delegate Sub ListViewAddItem_delegate(ByVal Col1 As String, ByVal Col2 As String, ByVal Col3 As String, ByVal Col4 As String, ByVal Col5 As String, ByVal col6 As String, ByVal col7 As String, ByVal col8 As String)
Private Sub ListViewAddItem(ByVal Col1 As String, ByVal Col2 As String, ByVal Col3 As String, ByVal Col4 As String, ByVal Col5 As String, ByVal col6 As String, ByVal col7 As String, ByVal col8 As String)
If Me.listview1.InvokeRequired Then
Dim d As New ListViewAddItem_delegate(AddressOf ListViewAddItem)
Me.listview1.BeginInvoke(d, {Col1, Col2, Col3, Col4, Col5, col6, col7, col8})
Else
listview1.Items.Add(New ListViewItem(New String() {Col1, Col2, Col3, Col4, Col5, col6, col7, col8}))
End If
End Sub
Private Sub search()
listview1.Items.Clear()
'Dim tasks = New Task(1) {}
'For i As Integer = 0 To 1
'if i = 0 then
'tasks(i) = Task.Run(AddressOf doSearch)
'elseif i = 1 then
'tasks(i) = Task.Run(AddressOf doOtherSearch)
'end if
'Next
'Task.Factory.ContinueWhenAll(tasks, Sub()
' Debug.Print("all threads done")
' End Sub)
'Do Until (tasks(0).Status = 5 And tasks(0).Status = 5)
' Application.DoEvents()
'Loop
'Task.WaitAll(tasks)
Parallel.For(0, 3, Sub(i)
if i = 0 then
doSearch()
elseif i = 1 then
doOtherSearch()
end if
End Sub)
checkWishlist()
End Sub
Public Sub checkWishlist()
For Each lvi As ListViewItem In listview1.Items
thisSelectCommand.CommandText = "SELECT * FROM wishlist WHERE ID='" & lvi.SubItems(6).Text & "'"
reader = thisSelectCommand.ExecuteReader
If reader.HasRows = True Then
lvi.ForeColor = Color.Red
Else
lvi.ForeColor = Color.Black
End If
reader.Close()
Next
End Sub
public sub doSearch()
for i as integer = 0 to 100
ListViewAddItem("Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8")
next
End sub
public sub doOtherSearch()
for i as integer = 0 to 100
ListViewAddItem("Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8")
next
End sub
【问题讨论】:
-
在单独的线程(或任务等)中运行查询,然后将它们添加到主线程的列表视图中。
-
你的意思是我应该在任务中运行她的 sql 查询并在使用“ListViewAddItem”之前设置前景色还是?
-
您可以使用 SYNCLOCK 但这只会减慢您的速度。但它会起作用。
标签: vb.net multithreading listview