现在我有多个窗体A(主窗体),B,C..。A中有TIMER1,B中也有TIMER2。
B窗体一直是打开的,TIMER2.Interval = 1000,而且在执行事件。
当我在A窗体中打开C窗体时,B窗体中的TIMER2大部分会停止事件(直到关闭C窗体回到A窗体,B窗体中的事件继续执行。)
有时会继续执行。是线程问题吗?

解决方案 »

  1.   

    是线程问题。
    由于vb6对回调函数支持不够好,实现多线程是非常麻烦的。改用ACTIVE EXE吧
      

  2.   

    那咋整...不是有CreateThread创建一个多线程方法的吗?
      

  3.   

    你可以创建,但是VB创建的多线程很不稳定,我试过很多次,都以失败告终。如有兴趣,你可以看看这本书,里面有对多线程的介绍。
    http://download.csdn.net/source/1371398
      

  4.   

    楼上的推荐那书 建议一般人别看 (太深了,没有深厚的COM基础根本看不懂),看那书还不如看 vb6编程技术大全。
      

  5.   

    TIMER2是基于消息的。中断程序。
    如果你是模态窗口打开其他的就阻塞了TIMER2所在窗体消息触发。
      

  6.   

    楼主要知道,即使用C的多线程,当CPU被其它优先级更高的线程占用时,你的线程仍然会因得不到CPU而暂停执行的。
      

  7.   

    是不是太占资源了,影响了别的流程执行啊.编译后,就算是弹个MsgBox也不会卡起Timer的.
      

  8.   

    那个B窗体就是一直开着的,不停的执行一些循环语句(不是死循环)。
    但是A窗体操作C的时候就发生上面的情况。
    马哥
      

  9.   

    模态窗口不会挂起编译后的Timer.但是就算是多线程,如果你有抢CPU的过程,类似死循环那样,别的线程也一样受影响.关键是看你那两个窗体都干了些啥.这里面的信息越详细越好.
      

  10.   

    老马 我来了.....
    'B窗体的代码
    Private Declare Function CreateRectRgn Lib "gdi32.dll" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hrgn As Long, ByVal bRedraw As Long) As Long
    Private Declare Function CombineRgn Lib "gdi32.dll" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
    Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
    'Event
    Private Enum AnimeEventEnum
        aunload = 0
        aload = 1
    End Enum
    'Special effect
    Private Enum AnimeEffectEnum
        eAppearFromLeft = 0
        eAppearFromRight = 1
        eAppearFromTop = 2
    End Enum
    Private Const RGN_AND  As Long = 1
    Private Const RGN_OR   As Long = 2
    Private Const RGN_XOR  As Long = 3
    Private Const RGN_DIFF As Long = 4
    Private Const RGN_COPY As Long = 5
    '********************
    '我担心问题出在这里的Sleep
    Private Function AnimateForm(hwndObject As Object, ByVal aEvent As AnimeEventEnum, _
                                Optional ByVal aEffect As AnimeEffectEnum = 11, _
                                Optional ByVal FrameTime As Long = 1, _
                                Optional ByVal FrameCount As Long = 33) As Boolean
    On Error GoTo Error:
    Dim X1, Y1          As Long
    Dim hrgn, tmpRgn    As Long
    Dim XValue, YValue  As Long
    Dim XIncr, YIncr    As Double
    Dim wHeight, wWidth As Long
        
        wWidth = hwndObject.Width / Screen.TwipsPerPixelX
        wHeight = hwndObject.Height / Screen.TwipsPerPixelY
        hwndObject.Visible = True
        
        Select Case aEffect
            Case eAppearFromLeft
                XIncr = wWidth / FrameCount
                For X1 = 0 To FrameCount
                    'Define the size of current frame/Create it
                    XValue = X1 * XIncr
                    hrgn = CreateRectRgn(0, 0, XValue, wHeight)
                    'If unload then take the reverse(anti) region
                    If aEvent = aunload Then
                        tmpRgn = CreateRectRgn(0, 0, wWidth, wHeight)
                        CombineRgn hrgn, hrgn, tmpRgn, RGN_XOR
                        DeleteObject tmpRgn
                    End If
                    'Set the new region for the window
                    SetWindowRgn hwndObject.hwnd, hrgn, True: DoEvents
                    Sleep FrameTime
                Next X1
            Case eAppearFromRight
                XIncr = wWidth / FrameCount
                For X1 = 0 To FrameCount
                    XValue = wWidth - X1 * XIncr
                    hrgn = CreateRectRgn(XValue, 0, wWidth, wHeight)
                    If aEvent = aunload Then
                        tmpRgn = CreateRectRgn(0, 0, wWidth, wHeight)
                        CombineRgn hrgn, hrgn, tmpRgn, RGN_XOR
                        DeleteObject tmpRgn
                    End If
                    SetWindowRgn hwndObject.hwnd, hrgn, True:  DoEvents
                    Sleep FrameTime
                Next X1
            Case eAppearFromTop
                YIncr = wHeight / FrameCount
                For Y1 = 0 To FrameCount
                    YValue = Y1 * YIncr
                    hrgn = CreateRectRgn(0, 0, wWidth, YValue)
                    If aEvent = aunload Then
                        tmpRgn = CreateRectRgn(0, 0, wWidth, wHeight)
                        CombineRgn hrgn, hrgn, tmpRgn, RGN_XOR
                        DeleteObject tmpRgn
                    End If
                    SetWindowRgn hwndObject.hwnd, hrgn, True:   DoEvents
                    Sleep FrameTime
                Next Y1
             End Select
        AnimateForm = True
    Exit Function
    Error:
        AnimateForm = False
    End FunctionPrivate Sub ImgTimer_Timer()
        Advertisement
    End SubPrivate Sub Advertisement()
    Dim sEffect  As Integer    sEffect = Int(Rnd * 2)
        AnimateForm Pic, aload, sEffect, 15, 30
    End SubPrivate Sub Form_Load()    sSpecialTime = oIni.ReadKey("TableManager", "SpecialTime")
        If sSpecialTime = "NOT EXIST" Then
            sSpecialTime = "0"
            oIni.WriteKey "TableManager", "SpecialTime", "0"
        End If
        
        sSpecialCount = oIni.ReadKey("TableManager", "SpecialCount")
        If sSpecialCount = "NOT EXIST" Then
            sSpecialCount = "0"
            oIni.WriteKey "TableManager", "SpecialCount", "0"
        End If    ImgTimer.Interval = 1000
        Me.Move oMSA.MiscArea3.Width, 1000, oMSA.MiscArea3.Width, oMSA.MiscArea3.Height
        MakeTransparent Me.hwnd, 5
    End Sub
      

  11.   

    确实,前不久为了注册ROT,才用到了里面的vboost库。
      

  12.   

    你把怀疑的地方注释掉看看.我看你这每个分支都是循环,如果这个过程被调用很频繁,那就很占CPU的.你试试在SLEEP后面加doevents看看,而不是在前面.SLEEP后才是有可能积累消息的时候..
      

  13.   

    模态是不影响Timer的运行。执行间隔一秒,没看错的话,你的Timer事件代码里,执行循环34次,每次程序睡一会,就算一次睡30毫秒,程序触发一次执行时间超过1秒间隔了,然后Timer再一次被触发,你可以打印时间看看。为什么要加Sleep呢?
      

  14.   

    老马,在后面加DOEVENTS也是一样的效果。
      

  15.   

    vb虽然是单线程的,但是timer是事件,
    事件就会中断,何况是2个窗体的timer
    好在还是单线程,用全局变量可以很好解决
      

  16.   

    就是 Sleep 的问题,它挂起了当前进程,当然也包括了 Timer 事件。
    改用 SetTimer 创建高精度的定时器,来进行帧的循环。
      

  17.   

    老鸟来了..SetTimer函数怎么用?
    Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    是这样用吗?SetTimer form1,lmgtimer,30,null
      

  18.   

    老鸟,怎么用SETTIMER来代替SLEEP?
      

  19.   

    给你一个例子加
    Command1
    ProgressBar1*******************************
    模块里Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    Public id_timer As Integer '用来存放返回的定时器的ID
    Const inc_step As Integer = 5 '设置ProgressBar值的增量'Starttimer过程调用SetTimer函数生成定时器,hwnd和nIDEvent送入0表示在回调过程中不使用它们,uElapse置为100,让程序每100毫秒就调用一次回调函数;lpTimerFunc参数由AddressOfTimerProc将
    'TimerProc的地址送入函数.Public Sub StartTimer()
        id_timer = SetTimer(0, 0, 100, AddressOf TimerProc)
        Form1.ProgressBar1.Value = 0
        Form1.Command1.Caption = "Stop"
    End Sub
    'Endtimer清除定时器,同时给用户一个信息反馈。
    Public Sub EndTimer()
        KillTimer 0, id_timer
        id_timer = 0
        MsgBox "Timer has been killed!", vbExclamation, "Done!"
        Form1.Command1.Caption = "Start"
    End Sub'Updateprogressbar过程用来更新进程条的显示。
    Public Sub updateprogressbar()
        Dim percentdone As Integer
        percentdone = Form1.ProgressBar1.Value + inc_step
        
        If percentdone > 100 Then
            Form1.ProgressBar1.Value = 100
            EndTimer
        Else
            Form1.ProgressBar1.Value = percentdone
        End If
    End Sub'----建立回调过程,这里回调过程只是调用updateprogressbar过程来更新显示。
    Public Sub TimerProc()
        updateprogressbar
    End Sub窗体Private Sub Command1_Click()
        If id_timer > 0 Then
            EndTimer
        Else
            StartTimer
        End If
    End Sub