VB2005 禁止控件自动刷新问题

oo渣渣oo 2010-05-21 05:31:44
=== 现状:

我的项目中做了一个加载数据行的窗口,用ListView显示数据,此窗口暂且称为Form1.

由于数据比较多,大概有2000多行,我就用了另一个窗口带ProgressBar的方式还显示加载的进度,此窗口暂且称为Form2.

同时时,为了让ProgressBar窗口(Form2)正常显示,我在Form1的加载循环中用了Application.DoEvents()来释放CPU占用.

=== 问题:
Application.DoEvents()用了以后,加载数据明显变慢了,加载时间是不用Application.DoEvents()的几倍!

我判断是因为ListView在不断地重绘导致消耗了过多的CPU时钟.

=== 尝试过的方法:
1. 用SuspendLayout()和ResumeLayout()想停止控件刷新,未果.
2. 用Visible = False的方式倒是不错,加载速度明显恢复了,但是界面太难看....

=== 求解:
有没有高级点的方式,来实现以下目的?

1.不要隐藏ListView控件,加载数据过程中Form1或ListView不刷新,直至加载完毕后一次性显示.

2.同时又要保证ProgressBar窗口(Form2)能正常刷新.

...全文
417 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
oo渣渣oo 2010-05-26
  • 打赏
  • 举报
回复
不好意思,搞忘记了......现在就分!
Forrest23 2010-05-25
  • 打赏
  • 举报
回复
怎么还没分脏?
oo渣渣oo 2010-05-24
  • 打赏
  • 举报
回复
哇,好多回答,慢慢研究中..........
皇城龙三 2010-05-24
  • 打赏
  • 举报
回复
取出来先赋值给一个数组,再填充listview
oo渣渣oo 2010-05-24
  • 打赏
  • 举报
回复
问题已解决,把所有数据先丢到ListViewItem的数组中,最后再添加到控件内.

虽然大家的意见没用上,不过辛苦费还是有滴,分脏........
Forrest23 2010-05-22
  • 打赏
  • 举报
回复
以前也做过一个 用另外一个窗体来显示进度条的窗体
’写了个函数 主要代码如下

If Number = 0 Then
frmProgress.Show()
frmProgress.prgbar.Value = Number
frmProgress.Label1.Text = str_caption
ElseIf Number = 100 Then
frmProgress.prgbar.Value = Number
frmProgress.Label1.Text = str_caption
frmProgress.Close()
frmProgress.Dispose()
Else
frmProgress.prgbar.Value = Number
frmProgress.Label1.Text = str_caption
End If
frmProgress.Refresh()
'这样可以进度条窗体可以正常显示 并不需要加 Application.DoEvents()

messi_yang 2010-05-22
  • 打赏
  • 举报
回复
來學習哈····
ncqingchuan1976 2010-05-22
  • 打赏
  • 举报
回复
两个窗体form1,form2 form1上有控件button 名OKBtn,listview名LV。form2上有processbar 名PB
form1代码

Public Class Form1
Private m_Count As Integer
Dim PrcentForm As Form2
Private Delegate Sub PrcentChangeDelegate(ByVal Prcent As Integer)

Public ReadOnly Property Count() As Integer
Get
Return m_Count
End Get
End Property
Private Sub OKbtn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles OKbtn.Click
LV.Items.Clear()
PrcentForm = Form2
PrcentForm.Show()

Dim i As Integer = 0
While i <= m_Count '模拟加载数据
PrcentForm.Invoke(New PrcentChangeDelegate(AddressOf PrcentForm.DisPlayVal), New Object() {CInt((i / (m_Count)) * 100)})
LV.Items.Add(i)
LV.Items(i).SubItems.Add(i)
i += 1
End While
PrcentForm.Close()

End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
LV.Columns.Add("数据", 200, HorizontalAlignment.Center)
m_Count = 10000
Control.CheckForIllegalCrossThreadCalls = False
End Sub

End Class

form2代码

Public Sub DisPlayVal(ByVal Prcent As Integer)
PB.Value = Prcent

End Sub



不知是否是你要的效果.
ncqingchuan1976 2010-05-22
  • 打赏
  • 举报
回复
采取异步方式
以下须一个button,processbar

Public Class Form3
Private Delegate Function DisPlayText(ByVal Intput As Long)

Private Delegate Sub DisValue(ByVal Value As Integer)

Private exv As Boolean

Private Sub PbValue(ByVal Value As Integer)
PB.Value = Value
End Sub
Private Sub metext(ByVal text As Long)
Me.Text = text.ToString
End Sub
Dim iresult As IAsyncResult
Dim A As DisPlayText
Private Function Cal(ByVal Intput As Long) As Integer
Dim i As Long
Dim t As Long
For i = 0 To Intput
t = i + 1
Me.Invoke(New DisValue(AddressOf PbValue), CInt((i / Intput) * 100))
Next
Return t
End Function
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
If Not exv Then

Try
A = New DisPlayText(AddressOf Cal)
iresult = A.BeginInvoke(100000, New AsyncCallback(AddressOf CallBack), Nothing)
Catch ex As Exception

Finally
exv = True
End Try

End If

End Sub

Private Sub CallBack()

Try
Dim i As Integer = A.EndInvoke(iresult)
Me.Invoke(New DisValue(AddressOf metext), i)
Catch ex As Exception

Finally

exv = False
End Try

End Sub

End Class
ncqingchuan1976 2010-05-22
  • 打赏
  • 举报
回复
两个窗体
form1 控件datagridview:datagridview1 ,button:OKbtn
form2 控件ProcessBar:PB
通过异步调用实现楼主的方法,且FORM2窗体不会出现未响应,代码如下:

Imports System.ComponentModel

Public Class Form1
Private m_Count As Integer '

Dim PrcentForm As Form2

Private Delegate Sub PrecentChangeDelegate(ByVal Precent As Integer)
Private Delegate Sub RunDelegate()
Private Delegate Sub CompleteDelegate()

Private Asyresult As IAsyncResult
Private List As BindingList(Of Datalist)

Private Run As RunDelegate
Public Sub DisPlayPrecent(ByVal Precent As Integer)
PrcentForm.PB.Value = Precent
If Precent = 100 Then
PrcentForm.Close()
End If
End Sub

Private Sub OKbtn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles OKbtn.Click

m_Count = 40000
PrcentForm = Form2
PrcentForm.Show()


Run = New RunDelegate(AddressOf LoadData) '异步调用数据加载过程
Asyresult = Run.BeginInvoke(New AsyncCallback(AddressOf CallBack), Nothing)

End Sub

Private Sub CallBack() '通过回调实现绑定
Run.EndInvoke(Asyresult)
Me.Invoke(New CompleteDelegate(AddressOf BindingData))

End Sub

Private Sub BindingData() '绑定到DataGridView1
Me.DataGridView1.DataSource = List
End Sub

Private Sub LoadData() '模拟加载数据
List = New BindingList(Of Datalist)
List.Clear()
Dim i As Integer = 0
While i <= m_Count
Dim T As New Datalist(i)
Me.Invoke(New PrecentChangeDelegate(AddressOf DisPlayPrecent), New Object() {CInt(i / m_Count * 100)})
List.Add(T)
i += 1
End While
End Sub
End Class


Public Class Datalist '数据模型
Private m_Number As Integer
Public ReadOnly Property Number()
Get
Return m_Number
End Get
End Property
Public Sub New(ByVal I As Integer)
m_Number = I
End Sub

End Class
足球中国 2010-05-22
  • 打赏
  • 举报
回复
Application.DoEvents()的意思楼主要看一下。
这个是vb那引过来的。
是把操作权交给系统。交给系统意味着。你的程序所分配的各种资源会重新分配。这样会导致你的程序变慢。
你可以用线程来处理这个东东。
sxmonsy 2010-05-22
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!
skep99 2010-05-21
  • 打赏
  • 举报
回复
数据库加载到容器后再绑定 ListView
ListView用虚模式显示
2000行也就一眨眼,根本用不着ProgressBar来显示
水哥阿乐 2010-05-21
  • 打赏
  • 举报
回复
学习,帮顶
古今多少事 2010-05-21
  • 打赏
  • 举报
回复
那你用两个ListView,一个用来显示,真正加载数据的隐藏,加载完再显示。

16,722

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧