Results 1 to 7 of 7

Thread: [RESOLVED] Callback Sub causes App to crash on Form_Unload

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Resolved [RESOLVED] Callback Sub causes App to crash on Form_Unload

    Everytime I unload the app it crashes. I have narrowed it down to code in a callback sub but for the likes of me I can't understand why the code will cause the crash.

    Here is the callback sub in a BAS module

    Code:
    Public Sub WaveCallbackProc(ByVal hwi As Long, _
                                ByVal uMsg As Long, _
                                ByVal dwInstance As Long, _
                                ByVal dwParam1 As Long, _
                                ByVal dwParam2 As Long)
     
     Select Case uMsg
       Case MM_WIM_OPEN
         ' Here when waveInOpen called
    
     
       Case MM_WIM_DATA
         ' Here when sound buffer is full
      
       Case MM_WIM_CLOSE
         ' Here when waveInClose called
       
       Case MM_WOM_OPEN
         ' Here when waveOutOpen called
       
       Case MM_WOM_DONE
         'Here when sound buffer has finished or empty
    
         Form1.Timer1.Enabled = False
         Form1.picFreq(0).Cls
         Form1.picFreq(1).Cls
         Form1.Command2.Enabled = False
         Form1.Command1.Enabled = True
         
       Case MM_WOM_CLOSE
         ' Here when waveOutClose called
    
     End Select
    End Sub
    Here is the Form_Unload

    Code:
    Private Sub Form_Unload(Cancel As Integer)
     Timer1.Enabled = False
    End Sub
    Here is the Timer Sub

    Code:
    Private Sub MyTmrVis_Timer()
     On Error GoTo ER
    
     CopyMemory intSamples(0), WavSound(iOffset), FFT_SAMPLES
     
     iOffset = iOffset + FFT_SAMPLES
       
     DrawFrequencies intSamples, picFreq(0), picFreq(1)
    
     Exit Sub
    ER:
     Form1.MyTmrVis.Enabled = False
     Form1.picFreq(0).Cls
     Form1.picFreq(1).Cls
     Form1.Command2.Enabled = False
     Form1.Command1.Enabled = True
     CloseWaveOut
    End Sub
    In all cases I have not unloaded the App until after the code in the callback had finished so that means I do not kill app during the sound out (playing) time.

    The only error that could occur in the timer sub is an index out of bounds but in the case of my testing that does not occur because the size of the WavSound buffer is exactly divisible by FFT_SAMPLES so I never get an odd results which would cause the CopyMemory function to fail and it is in sync with the callback sub which means that the callback at Case MM_WOM_DONE is executed when the last chunk has be extracted from the buffer in the timer event.


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  2. #2
    Hyperactive Member Lenggries's Avatar
    Join Date
    Sep 2009
    Posts
    353

    Re: Callback Sub causes App to crash on Form_Unload

    Do you get a meaningful error message when the crash occurs? If so, what is it?

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: Callback Sub causes App to crash on Form_Unload

    It's one of those VB has encounter a problem and must shut down, Sorry for the inconvience type. I know it has to do with the callback as I ran the same app without the callback and it doesn't crash. I know that you cannot call APIs while in the callback as I have already dealt with that problem so I'm guessing that the code in the callback is executing calls into the VB runtime module which I have been told will also cause unexpected results. I have a work around for this if it turns out I won't be able to use the callback with that code in it. I can put a boolean variable in place of the present code and set it to True when Case MM_WOM_DONE is called by the MM system then in my regular code I just test for that and then execute the same code outside of the callback. I would rather use the callback if at all possible with the code I presently have in it.


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  4. #4
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Callback Sub causes App to crash on Form_Unload

    Quote Originally Posted by jmsrickland View Post
    I know that you cannot call APIs while in the callback....
    You know wrong. What you can't do is use a Declare Function since that has to do an interpretive thunk to resolve the entrypoint at runtime (and this requires that the thread at least have COM initialized on it, and probably other things to "reach" the VB runtime).

    Quote Originally Posted by jmsrickland View Post
    ... so I'm guessing that the code in the callback is executing calls into the VB runtime module which I have been told will also cause unexpected results.
    Your callback cannot touch anything but simple variables declared in a static (.BAS) module. No objects, including Forms, Controls, etc. This is also, at least in part, because the multimedia thread does not have COM initialized on it.


    Basically you have about 3 options:

    • Use something like a static Boolean that your UI thread (your VB code outside the callback) polls using a Timer control.
    • Send a user message to the hWnd of a Form or UserControl which is subclassed to pick it up and process it.
    • Skip all of this and just use subclassing in the first place to handle these multimedia messages.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: Callback Sub causes App to crash on Form_Unload

    Sounds good


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  6. #6
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: [RESOLVED] Callback Sub causes App to crash on Form_Unload

    If that Schmidt guy takes an interest he might have more detail to contribute. He dives deeper into COM and VB issues than most of us need to.

  7. #7
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: [RESOLVED] Callback Sub causes App to crash on Form_Unload

    Sorry, discovered this invitation a bit late ... ;-)

    Well, decoupling with Typelib-defined Calls, usually per PostMessage and then leaving the CallBack as fast as possible -
    this approach was already mentioned - and that's what works and what I usually do as well (when we talk about Callbacks from different threads)...
    which would be definitely the issue e.g. with the Multimedia-Timer-Callbacks ...

    Not sure, if the WaveIn-callbacks fall into the same (foreign threaded) category, since I never forced those (by passing a Zero-Param)
    whilst working with the WaveIn-API ... a normal polling per API-Timer (which may serve here now as an example for:
    "friendly and secure callbacks on the same thread") was entirely enough.

    Here's some code, not in the context of a working example, but "copied as found" from an already 13 year old Demo, which still works here.

    It is using a (class-encapsulated) API-Timer - in conjunction with a RingBuffer-Array (and -Indexing).
    Maybe that worth' a look from jmsrickland

    Code:
    Private Type Stereo
      L As Integer
      R As Integer
    End Type
    
    Private Type FFTStereo
      L As Double
      R As Double
    End Type
    
    Private Type WaveHdr
        lpData As Long
        dwBufferLength As Long
        dwBytesRecorded As Long
        dwUser As Long
        dwFlags As Long
        dwLoops As Long
        lpNext As Long 'wavehdr_tag
        reserved As Long
    End Type
    
    Private Type WavBuf
      Hdr As WaveHdr
      Arr(1023) As Stereo '23 msec (4kB ByteSize - and 43Hz at 44100)
      FFT(1023) As FFTStereo
    End Type
    
    Private RBuf(29) As WavBuf, RIdx&, xt 'As APITimerClassEncapsulation
    
    Private Sub DoStop()
    Dim i&
      xt.Enabled = False
      If DevHandle Then
        For i = 0 To UBound(RBuf)
          waveInUnprepareHeader DevHandle, RBuf(i).Hdr, Len(RBuf(i).Hdr)
        Next i
        waveInReset DevHandle
        waveInClose DevHandle
        DevHandle = 0
      End If
    End Sub
    
    Private Sub xt_Timer() '<- API-Timer-Eventsink (the normal one, not a MultiMedia-Timer)
    Dim i&
      Do While RBuf(RIdx).Hdr.dwFlags And WHDR_DONE
        ProcessBuf RBuf(RIdx)
        RIdx = CIdx(RIdx + 1)
      Loop
      For i = RIdx To RIdx + UBound(RBuf)
        InitBuf RBuf(CIdx(i))
      Next i
    End Sub
    
    Private Sub InitBuf(Buf As WavBuf)
      If Buf.Hdr.dwUser Then Exit Sub
      With Buf.Hdr
        .dwUser = 1
        If .lpData = 0 Then .lpData = VarPtr(Buf.Arr(0))
        If .dwBufferLength = 0 Then .dwBufferLength = (UBound(Buf.Arr) + 1) * 4
        waveInPrepareHeader DevHandle, Buf.Hdr, Len(Buf.Hdr)
        waveInAddBuffer DevHandle, Buf.Hdr, Len(Buf.Hdr)
      End With
    End Sub
    
    Private Sub ProcessBuf(Buf As WavBuf)
      waveInUnprepareHeader DevHandle, Buf.Hdr, Len(Buf.Hdr)
      Buf.Hdr.dwFlags = 0
      Buf.Hdr.dwUser = 0
     'your Buffer-Handling-Code here
    End Sub
    
    Private Function CIdx&(ByVal Idx&)
      CIdx = Idx Mod (UBound(RBuf) + 1)
    End Function
    Olaf

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width