Re: Visual Basic 6.0 + WMM API not stable on P4 with HyperThreading
From: Gabriel Michaud (gmiNOchaSPAMud_at_dynacom.ca)
Date: 10/18/04
- Next message: Robert Lightbourne: "Re: WMV movie files no longer play"
- Previous message: Marc Wallace: "Re: SetAttr Query - Quick One"
- In reply to: Peter Iannucci: "Re: Visual Basic 6.0 + WMM API not stable on P4 with HyperThreading"
- Messages sorted by: [ date ] [ thread ]
Date: Mon, 18 Oct 2004 15:23:04 -0400
Peter,
We've also had problems with hyperthreading and asynchronous ADO; we disable
the secondary CPU using the SetProcessAffinity API. Microsoft acknowledged
the problem but it doesn't look like they're going to fix it. I'm not sure
what's causing this problem, but the ADO issue might be related to Visual
Basic and not ADO itself, and this could also explain your problem.
Here's the thread on microsoft.public.data.ado:
"Peter Iannucci" <vaumnou@gmail.com> wrote in message
news:O8B%232LGtEHA.2124@TK2MSFTNGP11.phx.gbl...
> The WMM API, among other Windows services, automatically creates
> additional threads in the host process to manage its activities,
> communicate with drivers, etc. Then, if I understand correctly, it
> executes call-back functions in those threads. VB tends to crash when its
> functions are called from other threads, because it is only STA safe. To
> get around this, my callback function uses SetTimer with the hWnd of the
> main form to schedule a new event in the main form. The callback looks
> like this:
>
> Public Sub CallBack(ByVal hDev As Long, ByVal uMsg As Long, ByVal
> dwInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long)
> Dim atom As Long
> atom = CreateAtom
> CallBacksInProgress.Add Array(uMsg, dwInstance, dwParam1, dwParam2),
> CStr(atom)
> SetTimer Form1.hwnd, atom, 0, AddressOf TimerProc
> End Sub
>
> CreateAtom is just a VB function that InterlockedIncrement()s a global
> long; I use this as a unique ID function. The only thread issues I can
> see in this function are Form1.hwnd (which is static anyway), CStr(), and
> the call to a global collection's Add method. Does CStr depend on
> ThreadLocalStorage stuff like other VB Runtime functions? It seems to
> work just fine on a single-processor machine.
>
> When the timer fires (which it does immediately), it sends a WM_TIMER
> event to Form1, which is processed in the next message handler loop. This
> occurs in the main thread, and then it executes TimerProc:
>
> Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent
> As Long, ByVal dwTime As Long)
> Dim data As Variant, i As Long, n As Long
> KillTimer Form1.hwnd, idEvent
>
> n = CallBacksInProgress.Count
> For i = n To 1 Step -1
> data = CallBacksInProgress(i)
> CallBack2 data(0), data(1), data(2), data(3)
> CallBacksInProgress.Remove i
> Next i
> End Sub
>
> Public Sub CallBack2(ByVal uMsg As Long, ByVal dwInstance As Long, ByVal
> dwParam1 As Long, ByVal dwParam2 As Long)
> Dim Class As clsStreamSnd
>
> Set Class = Classes(CStr(dwInstance))
> Class.CallBack uMsg, dwParam1, dwParam2
> End Sub
>
> As you can see, the CallBacksInProgress collection functions as a work
> queue (well, technically a work stack). Each timer event clears this
> queue, calling the CallBack methods of the associated classes. The gist
> of this whole module is to allow an unlimited number of classes to
> register callbacks through a global public method. They call a Register
> function to add themselves to the Classes collection, then an Unregister
> function to free the class reference. In between, they can accept
> callbacks from the API by passing their class instance atom to Windows as
> a dwInstance parameter for the global CallBack function. The event gets
> dispatched to the class's local CallBack function, which takes it from
> there.
>
> The end result of all this is that a new frame of audio gets
> waveOutWrite()'d every time an old one is completed. Then I just keep a
> buffer of 4-8 waveOutHeader blocks enqueued at all times, and voila!
> Streaming audio without glitches or UI lock-ups.
>
> As for my reasons for suspecting HyperThreading, well, I must say it's
> mostly conjecture at this point. I suspect it because, after finally
> getting the thing to work on a single-processor machine, the fact that it
> would crash reliably on a dual-processor machine and then start working
> again with HyperThreading off is very suspicious. I think it's a data
> collision because I'm not using any locks. Maybe I should rewrite the
> code so that it uses CriticalSections around access to globals? If I were
> writing an explicitly multithreaded application, i.e. with calls to
> CreateThread, I would agree absolutely that locks are necessary around
> global accesses. However, since this application is only implicitly
> multithreaded, it shouldn't be necessary.
>
> -Peter I.
>
> "Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in
> message news:u1SPnLDtEHA.3772@TK2MSFTNGP10.phx.gbl...
>> Sounds like we need some more information about where your threads are
>> coming from, and how you're using them Peter. Also, what leads you to the
>> "data collision" theory?
>>
>> By default, VB6 threads use the Single-Threaded Apartment model, and a
>> consequence of this is that they do not share any data -- not even
>> Module-level global variables. This was a deliberate design decision by
>> the
>> VB team to keep VB thread-safe within STA's.
>>
>> How you try and force VB to operate in a MTA (Multi-Threaded Apartment),
>> e.g. by using the CreateThread API, then it will almost certainly
>> crash --
>> unless you've done something extremely clever.
>>
>> Tony Proctor
>>
>
- Next message: Robert Lightbourne: "Re: WMV movie files no longer play"
- Previous message: Marc Wallace: "Re: SetAttr Query - Quick One"
- In reply to: Peter Iannucci: "Re: Visual Basic 6.0 + WMM API not stable on P4 with HyperThreading"
- Messages sorted by: [ date ] [ thread ]