主FORM1
Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim st As New start st.shedingtimer() End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 5 End Sub End Class
类START.VB
Public Class start Dim itimer As Integer = 0 Public Sub shedingtimer() Dim TimerMove As System.Timers.Timer TimerMove = New System.Timers.Timer With TimerMove AddHandler TimerMove.Elapsed, AddressOf TimerMove_Tick TimerMove.Interval = 1000 TimerMove.Start() End With End Sub Public Sub TimerMove_Tick(ByVal sender As Object, ByVal e As EventArgs) If itimer = 5 Then itimer = 0 Form1.ProgressBar1.Value = itimer MsgBox(itimer) Else itimer = itimer + 1 Form1.ProgressBar1.Value = itimer MsgBox(itimer) End If End Sub End Class
弄的这个Form1.ProgressBar1.Value
不更新,一点变化没有,请人给指导下吧。
最近很忙,也瞎解决一下问题,现在回顾一下:
本来的目的有点复杂,现在理了点头绪,就是我要做的是一个长费时的工作过程,比如下载100个网页,所以用TIMER,工具栏中的那个,一下就卡死界面了,用TIMER,开新线程,也这样。后来,看到有人说,那个也是主线程的子线程,所以依然会卡。然后,又发现有人说用TIMERS.TIMER,是一个独立的线程。于是就用这个了。
用上这个后呢,工作完成后,发现过程看不到。于是就又想到,弄个进度条。但是进度条给值过程中,直接将值给了进度条值,就从不是创建控件“ProgressBar1”的线程访问它。于是呢,就又弄委拖,用上委拖呢,发现只能用在当前FORM中,代码不能放到其它类中,我这个人呢有个习惯,不喜欢把代码放到FORM中,总是想把他放到一些类中去,另建一个.VB文件类,结果放里面不行。
各位说的,都郁闷着用不上,我再想下,另外,高人的那个,接口,实在看不懂,我再研究研究,我之所以说跟你的类似的解决方法就是,你说的,不能直接给值,需要用委拖。
暂时先到这,研究研究再来补充
我的问题,其实跟这个类似
http://bbs.csdn.net/topics/310188511
但是他这个没有给出最终解决办法,解决
不要引用System.Timers
使用System.Forms.Timers,对应事件为Tick
forms.tiemer,用这个卡界面呀
在tick事件里加一个Application.DoEvents();就解决了。
不太明白。能详细说下吗?
@webzhuazi: Application.DoEvents();的意思就是处理完当前没有做完的事再做下一个,比如你的界面更新和跑进度条,因为不是多线程,所以你的进度条实际上是跑了,但是界面卡着的,看不出来,所以,你在tick事件里加一个Application.DoEvents();就OK了,你加一下试试。
设置了进度表的值后需要调用Application.DoEvents();才可以显示
不太明白。能详细说下吗?
@webzhuazi:
也就是在你这段代码后
If itimer = 5 Then itimer = 0 Form1.ProgressBar1.Value = itimer MsgBox(itimer) Else itimer = itimer + 1 Form1.ProgressBar1.Value = itimer MsgBox(itimer) End If
添加上Application.DoEvents();就可以显示了,你可以动手试一试。
我觉得你这个应该根本就编译出错才对.
Form1是个类名, 而ProgressBar1不可能是Form1的静态属性吧?
你在另一个类start中用 Form1.ProgressBar1.Value = itimer 这样的语句, 这应该是不可能的.
你必须先获得主窗口的实例句柄.
比如, 在Program.cs中, 定义一个公共静态属性MainForm, 以VB的语法应该像这样:
Public Shared Property MainForm As Form1;
然后在主函数中:
MainForm=New Form1();
Application.Run(MainForm);
这样, 你就可以在任意场所获得主窗口的句柄了.
在start类中:
Application.MainForm.ProgressBar1.Value = itimer
你说的这个,有点靠谱,但是,太粗了呀,我还是不太明白,能详细说下吗?
@webzhuazi:
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim s As New Start s.StartTimer(Me) End Sub End Class Public Class Start Private _timer As System.Timers.Timer Private _form1 As Form1 Public Sub StartTimer(mainForm As Form1) _form1 = mainForm _timer = New Timers.Timer() _timer.Interval = 1000 AddHandler _timer.Elapsed, AddressOf Timer_Tick _timer.Start() End Sub Private Sub Timer_Tick() If (_form1.ProgressBar1.InvokeRequired) Then _form1.ProgressBar1.Invoke(New System.Threading.ThreadStart(AddressOf SetValue)) Else SetValue() End If End Sub Private Sub SetValue() If (_form1.ProgressBar1.Value >= 100) Then _timer.Stop() Else _form1.ProgressBar1.Value += 1 End If End Sub End Class
@夏狼哉:
谢谢你及大家的回复,我已经在网上,查到资料,用的是上面夏狼哉的方法,但是这个方法,只能在当前FORM中使用,不能放到其它的类中,有人是这样的说的,还想请问是,是这样吗?
不能用在,其它的类中吗?
@webzhuazi:
你如果想要这个类去操作多个不同的Form,可以通过接口实现,对上面的代码略做调整即可:
Public Interface IProgressSettable ReadOnly Property ProgressBar As ProgressBar End Interface Public Class Form1 Implements IProgressSettable Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim s As New Start s.StartTimer(Me) End Sub Public ReadOnly Property ProgressBar As ProgressBar Implements IProgressSettable.ProgressBar Get Return ProgressBar1 End Get End Property End Class Public Class Start Private _timer As System.Timers.Timer Private _form1 As IProgressSettable Public Sub StartTimer(mainForm As IProgressSettable) _form1 = mainForm _timer = New Timers.Timer() _timer.Interval = 1000 AddHandler _timer.Elapsed, AddressOf Timer_Tick _timer.Start() End Sub Private Sub Timer_Tick() If (_form1.ProgressBar.InvokeRequired) Then _form1.ProgressBar.Invoke(New System.Threading.ThreadStart(AddressOf SetValue)) Else SetValue() End If End Sub Private Sub SetValue() If (_form1.ProgressBar.Value >= 100) Then _timer.Stop() Else _form1.ProgressBar.Value += 1 End If End Sub End Class
如果有其它Form也想由Start类来操作进度条,只要implements一下IProgressSettable接口即可。
@夏狼哉:
你如果想要这个类去操作多个不同的Form,可以通过接口实现,对上面的代码略做调整即可:
你理解错了。我不是想去操作多个FORM,主要是,想把这个代码,放到一个单独的类中,像我原始代码似的,放到一个单独的类star.vb这里面,但是,放里面不管用,我查了一些资料,只能是在form1里面放置,不能放到类中,是这样吗?
@webzhuazi:
......
我只能说 I 服了You...
哪怕是同一个类都可以拆分放在不同的文件中, 更何况它们是完全没有关系的两个类?
文件是没有意义的.
而且...... 关键问题是, 这么简单的动作,你不会自己试一下吗?
@夏狼哉:
刚才有点小心得,原来我认为,放到不同的文件中,就是不同的类了,分类存放了。刚才我想到,放到哪里都一样。比如,我新建一个XC.VB,这里,其它是任意名字,都可以。里面内容是XC.CLASS,还可以放XC1.CLASS,XC2.CLASS,这些,在主程序中调用时,也是用NEW XC1,XC2,而不是只是一个XC,中就包括了,这几个。
也就是文件只是存方便查看的,存放的地方而已,并不代表有什么作用。是这样吧。
@webzhuazi:
是的! 一个文本中可以放N个类. 一个类也可以分布在N 个文件中(通过部分类功能实现).
编程的单位是命名空间, 类, 接口等, 你学编程的时候哪里讲过按文件划分编程单位的? 不管多少个文件, 在编译的时候都会汇总到同一个程序集中, 所以运行时根本不知道你在写程序的时候到底放了多少个文件.
用:System.Window.Form.Timer 里面有个Tick事件
或者用:BackgroundWorker 这个线程组件。。
forms.tiemer,用这个卡界面呀
@webzhuazi: 用多线程哦、、有个Invork方法的么