采用定时器起线程~~~具体就是做一个单独功能的定时器,定时时间很短(例子里设为1)作用就是调用下线程函数,然后就关闭自己定时器。代码如下
Private Sub Form_Load()
Timer1.Enabled = False
timer1.Interval =1
End Sub
Private Sub Timer1_Timer()   '专门开线程的定时器,开了以后马上关闭自己
call  newthread
Timer1.Enabled = False
End SubPrivate Sub Command1_Click()
Timer1.Enabled = true        '通过打开定时器开线程
end subPrivate Sub newthread()  '需要开的线程函数
...
...
end sub

解决方案 »

  1.   

    不是不可以,但非常麻烦。看看这个能否帮助你:http://blog.csdn.net/Modest/archive/2008/05/08/2416967.aspx
      

  2.   

    楼主明显没有了解多线程的概念。在VB当中使用多线程最大的问题是内存的隔离。由于VB(特指VB6及以下版本)原始设计并没有考虑到多线程,所以其解释器当中的内存管理也没有做线程隔离,从而导致在使用如CreateThread之类创建线程后,无法正常使用。唯一可行的办法就是通过COM调用,来实现隔离,包括使用ActiveX Exe内建COM对象来实现等等。
      

  3.   

    发表于:2008-06-24 10:20:071楼 得分:0 
    这种方式仍然是单线程,不能实现多线程。 为啥不是多线程呢,我调用完timer1,然后再调用timer1的时候,不管newthread()有没有执行完都会再起一个newthread()实例的。我只是觉得这种方法对于一些简单的应用可能是一个相当直接的解决方案。因为我已经在我的一个代码里通过这个方法实现了多线程,但是我担心可能带来一些问题。麻烦大家拓展下思维,不要根据经验来下结论。
      

  4.   

    创建线程所需要花费的时间并不大,所以没有必要使用Timer,或者在同一个线程(主线程)当中执行是在Command按下的消息,还是Timer消息并没有差别。
      

  5.   

    楼主的还是单线程,你试试下面的程序能输出多个时间吗?
    Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 1
    End SubPrivate Sub Timer1_Timer()  '专门开线程的定时器,开了以后马上关闭自己
    Call newthread(Now)
    Timer1.Enabled = False
    End SubPrivate Sub Command1_Click()
    Timer1.Enabled = True        '通过打开定时器开线程
    End SubPrivate Sub newthread(ByVal s As String)   '需要开的线程函数
        Do While True
            Debug.Print s
        Loop
    End Sub
      

  6.   

    汗,没注意,楼主所谓的newthread,竟然是在Timer当中直接Call,看来真如我在三楼说的,楼主压根儿就没理解什么是多线程,或者说也没有理解Timer的工作机制。
      

  7.   


    //看来还没有明白多线程的概念,呵呵~~~~~~举个例子给你:)假设有一天你在写代码~~~~然后突然你后背痒痒了~~~~如果此时你停下写代码的工作,转而挠痒痒去,就是等于你直接在按钮里CALL那个newthread()~~在你没挠完痒痒前,你是没办法继续写代码的~~~~因为你只有两只手(newthread返回前,按钮过程不会返回).再假设,这个时候,如果你有一个保姆,你可以告诉她,"帮我挠痒痒,在后背坐标为X,Y的地方~~~"于是你就可以继续做你的工作;但本质上这并不是你自己完成的,而是由保姆(操作系统)来替你完成的.(TIMER本质上是系统的一个回调,你给了一个回调时间)就如你的代码.继续.再再假设,如果你此时多长了两只手,那么你就可以用那两只手挠痒痒,再用剩下的两只手写代码~~~~这样才是真正的多线程.....也许比喻不是很合适,但大概的意思是这样了,看看能否明白吧:)
      

  8.   

    是呀,简单的说我要实现的功能是在我调用newthread()那个函数后,不用关心他是否完成,让newthread()在后台运行,直接去下一条语句这就类似开一个线程了本来的逻辑如下
    ......
    .......
    call newthread
    call anothersub
    要走到call anothersub这步,必须等call newthread,newthread()这个函数走完。
    但是使用本帖的机制后,......
    .......
    Timer1.Enabled = true   '通过定时器来起newthread()这个函数实例
    call anothersub
    走到call anothersub这步就步需要newthread()这个函数走完。是不是类似在主线程之外另外又开了个线程去做newthread(),这样的形式。而且同时能够多次调用newthread(),而不去考虑前一个newthread()是否完成。当然我也隐约觉得在使用定时器的时候,不能做到同一时间片上的开多线程,例如以下语句就可能只起一个newthread()函数实例
    Timer1.Enabled = true
    Timer1.Enabled = true
    而以下语句就能起2个实例
    Timer1.Enabled = true
    delay(1)   '延迟1秒
    Timer1.Enabled = true
    但是由于我目前的应用之间会有不少时间间隔所以这个问题还不敏感。
      

  9.   

    由于timer控件也是一个ActivX控件所以是不是在一些特定的应用里,可以利用timer实现一些多线程的功能
      

  10.   

    显然搂主对于多线程的概念还不是很清楚。如果newthread()是在一个独立的线程中运行的话,newthread()的运行情况应该是不会影响到VB主线程的运行的,但是实际上在newthread()返回之前主线程里的Timer1.Enabled = False 根本就不会运行,由此可见newthread()实际上还是在VB的主线程里运行,并没有产生新的线程。或许你会说在newthread()里使用Doevents语句后就可以在newthread()返回之前先运行Timer1.Enabled = False,但是实际上Doevents的作用是释放系统的控制权,正因为newthread()占用了VB的主线程,所以才需要释放以后才能执行Timer1.Enabled = False这个语句,由此也可以说明newthread()是在VB主线程里运行的,并没有建立新的线程。而Doevents只是改变了代码执行的优先级,在newthread()里面使用Doevents以后VB会优先执行其他代码,只有在空闲时才会执行newthread()里面的代码,如果有其他事件发生,VB会暂停执行newthread()里的代码,优先响应其他事件,等其他事件响应完成后再回来继续执行newthread()。所以这不是多线程
      

  11.   

    楼上的我代码的确是错了,在定时器里面,先关闭自己的Enabled 再调用newthread ()
    Private Sub Timer1_Timer()  '专门开线程的定时器,开了以后马上关闭自己 
    Timer1.Enabled = False 
    call  newthread 
    End Sub 
    我要实现的功能是调用完newthread ()后直接不等newthread ()走完就执行下一条语句,原来的代码
    ...... 
    ....... 
    call newthread 
    call anothersub 
    要走到call anothersub这步,必须等call newthread,newthread()这个函数走完。 
    那么我要实现调用完newthread ()后直接不等newthread ()走完就执行下一条语句本来可以
    ...... 
    ....... 
    creatthread(newthread ,.....)
    call anothersub 
    通过另外开一个线程来实现,但是vb6对creatthread()的支持不够,编译好执行会出错所以我用本帖的机制实现了这个需求
    ....... 
    Timer1.Enabled = true  '通过定时器来起newthread()这个函数实例 
    call anothersub 
    走到call anothersub这步就不需要newthread()这个函数走完。 
    这是一个标准的多线程的逻辑,所以我希望开贴讨论的是这么做带来的问题,而不是这么做是不是多线程
      

  12.   

    你可以说是一个通过消息机制进行任务的串行,但是并不能称之为多线程。这种串行,只能达到某一些特定的目的,但是并不能达到多线程的并行机制。对于消息的处理,当我现在有一个死循环在作业,并且没有任何消息处理(Call DoEvents),那么你什么Timer也交无济于事。但是线程却是相互独立。
      

  13.   

    我理解SHAKOE的意思.
    TIMER用起来确实可以隔绝其他代码的影响.TIMER在VB6的优先级是其他控件最高的.再加上上时间定时TIMER出现会出现一点偏差,跑不准了,所谓程序员老感觉TIMER耗资源的原因也就在于此.不过1楼的程序写得还是有点牵强.我觉得应该是把工作代码放到TIMER定时区间里干活,这样回避其他单线程代码对TIMER内代码的约束.
      

  14.   

    猪头,我实在不想用这个词来称呼你,但是除了这个称呼外我实在想不出更恰当的。14楼的回复是试图向你说明VB的运行机制,并同时说明你的这个想法或逻辑或这种实现方式并不是一个多线程,而仍然是个单线程,而不是为了指出Timer1.enabled=false这句代码的位置问题。你原来的代码
    ...... 
    ....... 
    call newthread 
    call anothersub
    是需要先执行newthread,等newthread完成返回后再执行anothersub你新的代码
    ....... 
    Timer1.Enabled = true  '通过定时器来起newthread()这个函数实例 
    call anothersub 
    是先执行anothersub,等anothersub完成返回后再过1个毫秒的时间再执行newthread。
    你认为在设置Timer1.enabled=true以后timer1就开始计时,1毫秒以后自动执行newthread,不用等到newthread返回你可以继续执行anothersub,newthread和anothersub可能会同时都在执行(anothersub执行时间超过1毫秒),但是实际上在执行Timer1.enabled=true以后Timer1并没有开始计时,而是等到Timer1.Enabled=true所在的这个过程或函数里面的所有代码都执行完成以后才会开始计时,再经过1毫秒的时间以后才会执行newthread里的内容。你的新代码和
    …………
    …………
    call anothersub
    call newthread
    这种发式的区别是浪费了1毫秒的等候时间!(call anothersub后面没有其他代码)
      

  15.   

    "在我调用newthread()那个函数后,不用关心他是否完成,让newthread()在后台运行,直接去下一条语句"//看看是下一条语句与TIMER事件里的一起执行了,还是顺序执行了?反正光说的话你可能听不进去~~~~那就直接用你的代码测试吧!!代码是你的,总没问题了吧~~~如果是多线程,两个MSGBOX理论上应该相隔1MS弹出来~~~'窗体上添加一个TIMER,一个COMMANDBUTTON.
    Option ExplicitPrivate Sub Form_Load()
        Timer1.Enabled = False
        Timer1.Interval = 1
    End SubPrivate Sub Timer1_Timer()  '专门开线程的定时器,开了以后马上关闭自己
        Call newthread
        Timer1.Enabled = False
    End SubPrivate Sub Command1_Click()
        Timer1.Enabled = True        '通过打开定时器开线程
        Call newthread2
    End SubPrivate Sub newthread()  '需要开的线程函数
        Dim I As Long, J As String    For I = 1 To 200000
            J = J & "A"         '字符串累加,很费时
        Next I
        MsgBox "OK-1"
    End SubPrivate Sub newthread2()  '需要开的线程函数
        Dim I As Long, J As String    For I = 1 To 200000
            J = J & "A"         '字符串累加,很费时
        Next I
        MsgBox "OK-2"
    End Sub看看你的同时执行的效果如何吧~~~~~
      

  16.   

    我再给个真正的多线程,看看又是什么样的效果.'多线程测试代码
    'BY 嗷嗷叫的老马
    '源代码需要使用P-CODE编译Option ExplicitPrivate Declare Function CreateThread Lib "kernel32.dll" ( _
         ByVal lpThreadAttributes As Long, _
         ByVal dwStackSize As Long, _
         ByVal lpStartAddress As Long, _
         ByVal lpParameter As Long, _
         ByVal dwCreationFlags As Long, _
         ByRef lpThreadId As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32.dll" ( _
         ByVal hObject As Long) As Long
    Private Declare Function WaitForSingleObject Lib "kernel32.dll" ( _
         ByVal hHandle As Long, _
         ByVal dwMilliseconds As Long) As Long
    Private Declare Function MessageBox Lib "user32.dll" Alias "MessageBoxA" ( _
         ByVal hwnd As Long, _
         ByVal lpText As String, _
         ByVal lpCaption As String, _
         ByVal wType As Long) As LongSub Main()
        Dim lRet1 As Long, lRet2 As Long, hThread As Long
        
        MessageBox 0, "开始测试过程!", "测试多线程", 0
        
        lRet1 = CreateThread(0, 0, AddressOf MyThread1, 0, 0, ByVal 0)      '建立线程
        lRet2 = CreateThread(0, 0, AddressOf MyThread2, 0, 0, ByVal 0)      '建立线程
        
        WaitForSingleObject lRet1, -1
        WaitForSingleObject lRet2, -1
        
        CloseHandle lRet1
        CloseHandle lRet2
        
        MessageBox 0, "结束测试过程!", "测试多线程", 0
    End SubPublic Function MyThread1() As Long
        Dim I As Long, J As String    For I = 1 To 200000
            J = J & "A"         '字符串累加,很费时
        Next I
        Call MessageBox(0, "OK-1", ".....", 0)
        MyThread1 = 1
    End FunctionPublic Function MyThread2() As Long
        Dim I As Long, J As String    For I = 1 To 200000
            J = J & "A"         '字符串累加,很费时
        Next I
        Call MessageBox(0, "OK-2", ".....", 0)
        MyThread2 = 1
    End Function运行,打开任务管理器,看看线程里面是不是多了两个线程.最好编译.IDE里虽然也是P-CODE,但万一要挂了又得重新整代码了.(我是直接在IDE里运行的,没有问题)
      

  17.   

    在VB里面使用线程,好象在IDE当中运行能看到效果,但是编译出来还是很容易挂起的。
      

  18.   


    的确只要用本地代码编译,在按下线程弹出的MSGBOX时就挂了.所以得用IDE里一样的P-CODE编译.......
      

  19.   

    不管是否使用P-CODE,当你让线程自然结束,那么肯定非法操作。如果是直接TerminateThread,那么进程就无法退出。
      

  20.   

    我这里还好IDE里执行时点完OK-1与OK-2后正常退出P-CODE编译后也是这样但本地代码编译后点任意一个OK-X就非法.......
      

  21.   

    一个多线程的演示(应该可以执行,本来VB的多线程支持就不佳,有问题也不足为奇)mdlThreadProc.bas
    Attribute VB_Name = "mdlThreadProc"
    Option ExplicitPublic l_Num As Long
    Public IsQuit As LongPublic Declare Function CreateThread Lib "kernel32" _
        (ByVal lpThreadAttributes As Any, _
         ByVal dwStackSize As Long, _
         ByVal lpStartAddress As Long, _
         lpParameter As Any, _
         ByVal dwCreationFlags As Long, _
         lpThreadID As Long _
        ) As LongPublic Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPublic Declare Sub Sleep Lib "kernel32" _
        (ByVal dwMilliseconds As Long)Public Declare Function TerminateThread Lib "kernel32" _
        (ByVal hThread As Long, _
         ByVal dwExitCode As Long _
        ) As Long
        
    Public Declare Function ResumeThread Lib "kernel32" (ByVal hThread As Long) As Long    Public Declare Function InterlockedIncrement Lib "kernel32" (lpAddend As Long) As LongPublic Declare Function InterlockedExchange Lib "kernel32" (Target As Long, ByVal Value As Long) As LongPublic Declare Function WaitForSingleObject Lib "kernel32.dll" _
        (ByVal hHandle As Long, _
         ByVal dwMilliseconds As Long _
        ) As Long'线程函数
    Public Sub ThreadProc(ByVal lpParam As Long)
      '判断是否通知退出
      Do While (InterlockedExchange(IsQuit, ByVal 0&) = 0&)
        '工作,l_Num自增
        Call InterlockedIncrement(l_Num)
        '等一秒
        Call Sleep(1000&)
      Loop
      
    End Sub
    frmMain.frm
    VERSION 5.00
    Begin VB.Form frmMain 
       Caption         =   "Form1"
       ClientHeight    =   3195
       ClientLeft      =   60
       ClientTop       =   345
       ClientWidth     =   4680
       LinkTopic       =   "Form1"
       ScaleHeight     =   3195
       ScaleWidth      =   4680
       StartUpPosition =   3  'Windows Default
       Begin VB.Timer Timer1 
          Interval        =   1000
          Left            =   1890
          Top             =   690
       End
    End
    Attribute VB_Name = "frmMain"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
    Option Explicit
      Dim hThread As Long
      Dim ThreadID As Long
    Private Sub Form_Load()
      hThread = 0&
      IsQuit = 0&
      '创建线程
      hThread = CreateThread(ByVal 0&, ByVal 0&, AddressOf ThreadProc, ByVal 0&, 0, ThreadID)
    End SubPrivate Sub Form_Unload(Cancel As Integer)
      Dim iRet As Long
      
      If hThread <> 0& Then
        '设置退出标志
        iRet = InterlockedExchange(IsQuit, ByVal 1&)
        '等一下
        'Sleep ByVal 100&
        iRet = WaitForSingleObject(ByVal hThread, 10&)
        '关闭线程句柄
        iRet = CloseHandle(ByVal hThread)
        hThread = 0&
      End If
    End SubPrivate Sub Timer1_Timer()
      '显示线程执行结果
      Caption = InterlockedExchange(l_Num, ByVal l_Num)
    End Sub
    Test.VBP
    Type=Exe
    Form=frmMain.frm
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\WINDOWS\system32\stdole2.tlb#OLE Automation
    Module=mdlThreadProc; mdlThreadProc.bas
    IconForm="frmMain"
    Startup="frmMain"
    HelpFile=""
    Title="Test"
    ExeName32="Test.exe"
    Path32=""
    Command32=""
    Name="Test"
    HelpContextID="0"
    CompatibleMode="0"
    MajorVer=1
    MinorVer=0
    RevisionVer=0
    AutoIncrementVer=0
    ServerSupportFiles=0
    VersionCompanyName=""
    CompilationType=-1
    OptimizationType=0
    FavorPentiumPro(tm)=0
    CodeViewDebugInfo=0
    NoAliasing=0
    BoundsCheck=0
    OverflowCheck=0
    FlPointCheck=0
    FDIVCheck=0
    UnroundedFP=0
    StartMode=0
    Unattended=0
    Retained=0
    ThreadPerObject=0
    MaxNumberOfThreads=1[MS Transaction Server]
    AutoRefresh=1
      

  22.   

    我现在对 嗷嗷叫的老马 的印象有所改观了,呵呵。
    我就想用msgbox来说事情的,老马描述得不错啊,支持
      

  23.   

    正在学习多线程。28楼的代码打算试一下。但是不太懂,特请教:
    是不是我把另外要执行的代码写在MyThread1里,然后调用一下它就会单独执行而不影响主程序呢?
      

  24.   


    传说那个功能叫做异步,而不是多线程
    两个功能有时候能同样的效果,如果被调用的代码被投射到系统里面去,则能够形成一个类似
    多线程的效果,但他还是单线程,这就相当于多层嵌套循环,加了一个向外跳N层的条件
    可以看看这个, pctgl.vbgood.cn 里面,有个我当初研究过的异步