none
Midi Callback Garbage collected RRS feed

  • Question

  • Here is my code in Form 1

    Public Class Form1
        Private Delegate Sub DelegateForSomeSub(ByVal arg0 As String)
    
        Public Sub SomeSub(ByVal arg0 As String)
            If Me.InvokeRequired Then
                Debug.Print("invoke")
                Me.Invoke(New DelegateForSomeSub(AddressOf AppendText), arg0)
                'GC.Collect()
    
            Else
                Debug.Print("append")
                AppendText(arg0)
            End If
            'Debug.Print(arg0)
    
        End Sub
    
        Private Sub AppendText(ByVal arg0 As String)
            TextBox2.Text = arg0
    
        End Sub
        Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
            midiInClose(hMidiIn)
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            ' open the first available midi input device
            midiInOpen(hMidiIn, 0, AddressOf MidiInProc, 0, CALLBACK_FUNCTION)
            ' For explanation of parameters, see http://msdn.microsoft.com/en-us/library/ms711610
            midiInStart(hMidiIn)
    
        End Sub
    End Class
    

    And here is the Module 1 Code:

    Module Module1
    
        'all the midi declarations
    
        Delegate Function MidiIn_Callback(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
        Public Declare Function midiInOpen Lib "winmm.dll" (ByRef lphMidiIn As Integer, ByVal uDeviceID As Integer, ByVal dwCallback As MidiIn_Callback, ByVal dwInstance As Integer, ByVal dwFlags As Integer) As Integer
        Public Declare Function midiInClose Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
        Public Declare Function midiInStart Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
        Public hMidiIn As Integer
        Public Const CALLBACK_FUNCTION As Integer = &H30000
    
        'these are public for debug purposes.
        Public frames As Int16
        Public seconds As Int16
        Public minutes As Int16
        Public hours As Int16
        Public timecode As Long
        Public byte1 As Byte
        Public byte2 As Byte
        Public nibble1 As Byte
        Public nibble2 As Byte
    
        
    
        Function MidiInProc(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
    
            'MTC is 2 bytes. Byte 1 is F1 (means its an MTC packet). Byte 2 is a frame counter & frame value
            byte1 = dwParam1 And &HFF
            'skip if it isnt a frame packet
            If byte1 <> &HF1 Then
                Return 0
                Exit Function
            End If
    
            'byte 2 is split into nibbles. MS Nibble is Message Type, LS Nibble is Message
            byte2 = dwParam1 >> 8
            nibble1 = byte2 And &HF
            nibble2 = byte2 >> 4
    
            'operate!
            Select Case nibble2
                Case 0  'frame lsb
                    'mask
                    frames = (frames And &HF0) Or nibble1
                Case 1  'frame msb
                    'shift
                    nibble1 = nibble1 << 4
                    'apply
                    frames = (frames And &HF) Or nibble1
                Case 2  'second lsb
                    'apply
                    seconds = (seconds And &HF0) Or nibble1
                Case 3  'second msb
                    'shift
                    nibble1 = nibble1 << 4
                    'apply
                    seconds = (seconds And &HF) Or nibble1
                Case 4  'minute lsb
                    'apply
                    minutes = (minutes And &HF0) Or nibble1
                    frames = frames + 1
                Case 5  'second msb
                    'shift
                    nibble1 = nibble1 << 4
                    'apply
                    minutes = (minutes And &HF) Or nibble1
                Case 6  'hours lsb
                    'apply
                    hours = (hours And &HF0) Or nibble1
                Case 7  'hours msb
                    'shift
                    nibble1 = nibble1 << 4
                    'apply
                    hours = (hours And &HF) Or (nibble1 And &H1)
            End Select
    
            If nibble2 = 1 Or nibble2 = 5 Then
                DirectCast(My.Application.OpenForms.Item("Form1"), Form1).SomeSub(hours & ":" & minutes & ":" & seconds & ":" & frames & " -- " & nibble2)
            End If
        End Function
    
    End Module
    t seems to work fine for a while, but when the application  it's been running for sometime, the .NET application will crash.

    It shows "Callbackoncollecteddelegate" error, it seems my delegate its not alive, how can i resolve that???

    Wednesday, February 22, 2012 9:38 AM

Answers

  • Hi,

    Such error indicates either a CLR defect or a heap corruption, the process will be terminated immediately, it doesn't make any sense to catch this exception;

    In this case, we should do a live debugging or capture a dump for further investigation.

    You can use WinDbg + SOS to debug such issue. use ADPlus to capture a dump file.

     

    ADPlus is shipped with Debugging Tools For Windows which available at here, you can try this command to capture a dump file:

    adplus -crash -o d:\dumps -pn MyApplication


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by Paul Zhou Thursday, March 1, 2012 2:24 AM
    Monday, February 27, 2012 9:23 AM

All replies

  • Hi,

    Such error indicates either a CLR defect or a heap corruption, the process will be terminated immediately, it doesn't make any sense to catch this exception;

    In this case, we should do a live debugging or capture a dump for further investigation.

    You can use WinDbg + SOS to debug such issue. use ADPlus to capture a dump file.

     

    ADPlus is shipped with Debugging Tools For Windows which available at here, you can try this command to capture a dump file:

    adplus -crash -o d:\dumps -pn MyApplication


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by Paul Zhou Thursday, March 1, 2012 2:24 AM
    Monday, February 27, 2012 9:23 AM
  • Hi,

    The issue as I see it is lost scope on the MidiInOpen function.  The resourse is being marked collectable when the sub exits.  I'm not sure of the best answer, but I would start with returning the value of the function MidiInOpen to a static variable.

    Static HoldRef as integer = MidiInOpen(...)

    This should persist the handle.  You may have noticed up to a few minutes of operating correctly before the GC cleaned it up.


    -QuickC

    Monday, February 27, 2012 3:19 PM