首页 新闻 会员 周边

收藏 System.Timers.Timer,不更新FORM进度条控件,请高手指导

0
悬赏园豆:200 [待解决问题]

主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

但是他这个没有给出最终解决办法,解决

webzhuazi的主页 webzhuazi | 初学一级 | 园豆:4
提问于:2012-11-09 20:35
< >
分享
所有回答(5)
0

不要引用System.Timers
使用System.Forms.Timers,对应事件为Tick

jason2013 | 园豆:1998 (小虾三级) | 2012-11-10 23:30

forms.tiemer,用这个卡界面呀

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-18 23:12
0

在tick事件里加一个Application.DoEvents();就解决了。

hexllo | 园豆:318 (菜鸟二级) | 2012-11-12 17:25

不太明白。能详细说下吗?

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-18 23:12

@webzhuazi: Application.DoEvents();的意思就是处理完当前没有做完的事再做下一个,比如你的界面更新和跑进度条,因为不是多线程,所以你的进度条实际上是跑了,但是界面卡着的,看不出来,所以,你在tick事件里加一个Application.DoEvents();就OK了,你加一下试试。

支持(0) 反对(0) hexllo | 园豆:318 (菜鸟二级) | 2012-11-19 08:55
0

设置了进度表的值后需要调用Application.DoEvents();才可以显示

Parry | 园豆:583 (小虾三级) | 2012-11-12 17:46

不太明白。能详细说下吗?

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-18 23:13

@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();就可以显示了,你可以动手试一试。

支持(0) 反对(0) Parry | 园豆:583 (小虾三级) | 2012-11-20 08:48
0

我觉得你这个应该根本就编译出错才对.

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

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 10:58

你说的这个,有点靠谱,但是,太粗了呀,我还是不太明白,能详细说下吗?

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-18 23:13

@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
支持(0) 反对(0) 夏狼哉 | 园豆:833 (小虾三级) | 2012-11-19 08:37

@夏狼哉: 


谢谢你及大家的回复,我已经在网上,查到资料,用的是上面夏狼哉的方法,但是这个方法,只能在当前FORM中使用,不能放到其它的类中,有人是这样的说的,还想请问是,是这样吗?

 

不能用在,其它的类中吗?

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-21 19:23

@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接口即可。

支持(0) 反对(0) 夏狼哉 | 园豆:833 (小虾三级) | 2012-11-21 20:22

@夏狼哉: 

 

你如果想要这个类去操作多个不同的Form,可以通过接口实现,对上面的代码略做调整即可:

 

你理解错了。我不是想去操作多个FORM,主要是,想把这个代码,放到一个单独的类中,像我原始代码似的,放到一个单独的类star.vb这里面,但是,放里面不管用,我查了一些资料,只能是在form1里面放置,不能放到类中,是这样吗?

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-26 08:22

@webzhuazi: 

......

我只能说 I 服了You...

哪怕是同一个类都可以拆分放在不同的文件中, 更何况它们是完全没有关系的两个类?

文件是没有意义的.

而且...... 关键问题是, 这么简单的动作,你不会自己试一下吗? 

支持(0) 反对(0) 夏狼哉 | 园豆:833 (小虾三级) | 2012-11-26 08:30

@夏狼哉: 

 

刚才有点小心得,原来我认为,放到不同的文件中,就是不同的类了,分类存放了。刚才我想到,放到哪里都一样。比如,我新建一个XC.VB,这里,其它是任意名字,都可以。里面内容是XC.CLASS,还可以放XC1.CLASS,XC2.CLASS,这些,在主程序中调用时,也是用NEW XC1,XC2,而不是只是一个XC,中就包括了,这几个。

 

也就是文件只是存方便查看的,存放的地方而已,并不代表有什么作用。是这样吧。

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-12-28 23:14

@webzhuazi: 

是的! 一个文本中可以放N个类. 一个类也可以分布在N 个文件中(通过部分类功能实现). 

编程的单位是命名空间, 类, 接口等, 你学编程的时候哪里讲过按文件划分编程单位的? 不管多少个文件, 在编译的时候都会汇总到同一个程序集中, 所以运行时根本不知道你在写程序的时候到底放了多少个文件. 

支持(0) 反对(0) 夏狼哉 | 园豆:833 (小虾三级) | 2012-12-29 09:18
-1

用:System.Window.Form.Timer 里面有个Tick事件

或者用:BackgroundWorker 这个线程组件。。

在 水 一 方 | 园豆:1097 (小虾三级) | 2012-11-16 16:06

forms.tiemer,用这个卡界面呀

支持(0) 反对(0) webzhuazi | 园豆:4 (初学一级) | 2012-11-18 23:14

@webzhuazi: 用多线程哦、、有个Invork方法的么

支持(0) 反对(0) 在 水 一 方 | 园豆:1097 (小虾三级) | 2012-11-19 09:19
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册