Home All Groups Group Topic Archive Search About

ActiveX.exe and RaiseEvent

Author
29 Jun 2006 4:12 PM
Galen Somerville
A VB6 ActiveX.exe raises an event which is seen by the VB6 App.

Same setup in VB2005. The event to be raised is in form frmSweep. As in VB6,
frmSweep is hidden when the events take place.

I know by actions on the screen and sounds in the speakers that VB2005 is
using the ActiveX.exe correctly.

However the events are never raised !!!

There are no Errors or Warnings shown after rebuilding the VB2005 App

Anyone have a clue as to why no events are raised?

Galen

Author
29 Jun 2006 4:56 PM
Chris Dunaway
Galen Somerville wrote:
> I know by actions on the screen and sounds in the speakers that VB2005 is
> using the ActiveX.exe correctly.
>
> However the events are never raised !!!

Can you show the code where you add handlers to the events?
Author
29 Jun 2006 5:38 PM
Galen Somerville
"Chris Dunaway" <dunaw***@gmail.com> wrote in message
news:1151600198.093941.106770@y41g2000cwy.googlegroups.com...
> Galen Somerville wrote:
>> I know by actions on the screen and sounds in the speakers that VB2005 is
>> using the ActiveX.exe correctly.
>>
>> However the events are never raised !!!
>
> Can you show the code where you add handlers to the events?
>

Aha, what does a typical event handler look like?

Galen
Author
29 Jun 2006 8:22 PM
Chris Dunaway
Galen Somerville wrote:
Show quoteHide quote
> "Chris Dunaway" <dunaw***@gmail.com> wrote in message
> news:1151600198.093941.106770@y41g2000cwy.googlegroups.com...
> > Galen Somerville wrote:
> >> I know by actions on the screen and sounds in the speakers that VB2005 is
> >> using the ActiveX.exe correctly.
> >>
> >> However the events are never raised !!!
> >
> > Can you show the code where you add handlers to the events?
> >
>
> Aha, what does a typical event handler look like?
>
> Galen

It would be a method that has a Handles clause at the end such as:

Public Sub EventHandler(<appropriate signature here>) Handles
ActiveXControl.EventName
End Sub
Author
29 Jun 2006 9:29 PM
Galen Somerville
Show quote Hide quote
"Chris Dunaway" <dunaw***@gmail.com> wrote in message
news:1151612543.151954.238040@i40g2000cwc.googlegroups.com...
>
> Galen Somerville wrote:
>> "Chris Dunaway" <dunaw***@gmail.com> wrote in message
>> news:1151600198.093941.106770@y41g2000cwy.googlegroups.com...
>> > Galen Somerville wrote:
>> >> I know by actions on the screen and sounds in the speakers that VB2005
>> >> is
>> >> using the ActiveX.exe correctly.
>> >>
>> >> However the events are never raised !!!
>> >
>> > Can you show the code where you add handlers to the events?
>> >
>>
>> Aha, what does a typical event handler look like?
>>
>> Galen
>
> It would be a method that has a Handles clause at the end such as:
>
> Public Sub EventHandler(<appropriate signature here>) Handles
> ActiveXControl.EventName
> End Sub
>

I now receive the events, thank you, but apparently they are coming in
faster than they can be handled. So I have some debugging to do.

It's funny to me as the original conversion, VB6 to VB2005, was so slow it
couldn't keep up with the USB device. So thanks to Olaf Schmidt I made a VB6
AvtiveX.exe where a separate thread handles getting the USB data. Now the
data comes in at the correct rate.

Hopefully it's in some little bit of code and not in the Graphics display
routines.

Galen
Author
30 Jun 2006 7:12 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your post.

I see that your problem of the "receiving event from VB6 ActiveX exe" is
now resolved. Please feel free to post here if you have other questions.


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
1 Jul 2006 5:34 PM
Galen Somerville
My App recieves real time HeartBeat data and draws the traces on the screen
much like an oscilloscope. Typically this is at 75 Heart beats per minute
which equates to 24 byte data packets coming in every 14.12 milliseconds.

VB6 can operate at a minimum of 200 Heart beats per minute which is a packet
every 5.29 ms.

Vb2005 fails if I use over 10 Heart beats per minute which is a packet every
88.24 ms !!!

Below is some of the pertinent details. Suggestions welcomed !!!!!!!!!


A VB6 ActiveX.exe contains the Cmain and Cthread classes

In Cmain which is same thread as Main App

Public Event BurstData(DatAry() As Byte)

Part of shared array used in Cmain and Cthread
ReDim DatAry(23)

A new thread is started as Cthread and 170 packets of 24 bytes are
collected.
Each collected packet sends a message to Cmain to raise the BurstData event.

In VB6 this is the event which is raised:
Private Sub GD_BurstData(DatAry() As Byte)
    If modMain.USBflag Then
        ModPgm.ErrFlg = True
    Else
        ModUSB.bytAry = DatAry
    End If
    ModUSB.dtStatus = 0
    modMain.USBflag = True
End Sub

In VB2005 this is the event which is raised:
    Private Sub GD_BurstData(ByRef DatAry As System.Array) Handles
GD.BurstData
        If modMain.USBflag Then
            ModPgm.ErrFlg = True
        Else
            ModUSB.bytAry = DatAry
        End If
        ModUSB.dtStatus = 0
        modMain.USBflag = True
    End Sub

Both Apps are in a loop with DoEvents looking for USBflag = True.
They then draw 6 horiz pixels worth of two channel traces.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:VoPoaSBnGHA.4632@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Thank you for your post.
>
> I see that your problem of the "receiving event from VB6 ActiveX exe" is
> now resolved. Please feel free to post here if you have other questions.
>
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
3 Jul 2006 7:09 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your update.

After I read your post on May 5 regarding "VB2005 timing/speed problem", I
think we're having the same problem here. Although you can now receive the
events promptly in ActiveX EXE from ActiveX DLL, you still have to raise
the events to VB2005, which will also hit the barrier of marshaling
performance.

Let's take a step back to the beginning of this problem. After reviewing
your previous post, I'm not clear on some points, would you please help me
on following points?
1) Do you have the source code of the ActiveX DLL which is used to read
from the USB device?
2) Does that ActiveX DLL use event to notify the client or client has to
periodically call it?

I'm looking forward to your update on this. Thanks.


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
3 Jul 2006 3:07 PM
Galen Somerville
Show quote Hide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:syKhY%23mnGHA.5892@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Thank you for your update.
>
> After I read your post on May 5 regarding "VB2005 timing/speed problem", I
> think we're having the same problem here. Although you can now receive the
> events promptly in ActiveX EXE from ActiveX DLL, you still have to raise
> the events to VB2005, which will also hit the barrier of marshaling
> performance.
>
> Let's take a step back to the beginning of this problem. After reviewing
> your previous post, I'm not clear on some points, would you please help me
> on following points?
> 1) Do you have the source code of the ActiveX DLL which is used to read
> from the USB device?
> 2) Does that ActiveX DLL use event to notify the client or client has to
> periodically call it?
>
> I'm looking forward to your update on this. Thanks.
>
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>

Go to my web site and get USBdrvr.zip
http://home.surewest.net/galen/download.html

Note the CallBackTrigger form
CThread.cls has a PostMessage
Cmain.cls has the CallBackForm_CheckRingBufferQueue

So events are raised automatically and the main App just recieves them.

Isn't there something like DirectCast that short circuits the marshaling?

Galen
Author
4 Jul 2006 7:37 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for the source code.

I've gone through the code and also done some research on the COM Interop
performance.

Based on my research, the bottleneck should be the BurstData event raised
from VB6. I've created some test projects to benchmark the difference
between VB6 and VB2005 handling the event. Handling the event in VB2005 is
much slower than in VB6. This is difficult to overcome due to the nature of
marshaling between COM and .NET.

After I reviewed the source code of the ActiveX DLL project, I think it's
possible to implement it in VB2005 using P/Invoke to call the USB device
APIs. Also, thread is supported in VB2005 natively.

Although P/Invoke still has some overhead, it's much faster than COM
Interop. Please see following documentation for more information on
Managed/Unmanaged Code Interoperability:

#An Overview of Managed/Unmanaged Code Interoperability
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/ht
ml/manunmancode.asp
This article provides basic facts about interoperability between managed
and unmanaged code, and guidelines and common practices for accessing and
wrapping unmanaged API from managed code and for exposing managed APIs to
unmanaged callers. Security and reliability considerations, performance
data, and general practices for development processes are also highlighted.

With every transition from managed code to unmanaged code (and vice versa),
there is some performance overhead. The amount of overhead depends on the
types of parameters used. The CLR interop layer uses three levels of
interop call optimization based on transition type and parameter types:
just-in-time (JIT) inlining, compiled assembly stubs, and interpreted
marshaling stubs (in order of fastest to slowest type of call).

Approximate overhead for a platform invoke call: 10 machine instructions
(on an x86 processor).

Approximate overhead for a COM interop call: 50 machine instructions (on an
x86 processor).


Here are some more resources on P/Invoke:

#Platform Invoke Tutorial
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/
vcwlkplatforminvoketutorial.asp

#.NET: P/Invoke Revisited -- MSDN Magazine, October 2004
http://msdn.microsoft.com/msdnmag/issues/04/10/NET/
Talks about: Marshaling Structures, Object Lifetime and Pinning, Marshaling
Value Types vs. Reference Types, StructLayoutAttribute, Non-Blittable
Marshaling.

#GotDotNet User Sample: Platform Invoke Samples
http://www.gotdotnet.com/community/usersamples/details.aspx?sampleguid=f6f4c
339-22fd-44bb-a4fc-cfd874527ffb
The platform invoke samples demonstrate how to call functions exported from
an unmanaged library: how to declare different types, how to use available
attributes to modify default behavior, how to use methods of the Marshal
class when needed, and which aspects of garbage collection and threading
could affect results.

#GotDotNet User Sample: Interop Declarations for Windows.h
http://www.gotdotnet.com/community/usersamples/details.aspx?sampleguid=f1dd7
0e4-c212-4a6f-bff7-c82e34c8836f
When a Win32 API is not exposed by the .NET framework you must manually
write an interop wrapper to access that API. Writing these wrappers is
difficult and error prone. This post includes C# definitions of many common
Win32APIs and their related data structures

#pinvoke.net: the interop wiki!
http://www.pinvoke.net
PINVOKE.NET attempts to address the difficulty of calling Win32 or other
unmanaged APIs in managed code (languages such as C# and VB.NET). This site
is a repository where you can find, edit, and add PInvoke signatures,
user-defined types. Think of this as the 21st century version of VB6's "API
Text Viewer".

Hope this helps. Please feel free to post here if anything is unclear.


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
4 Jul 2006 2:43 PM
Galen Somerville
On a much earlier thread in this newsgroup, I think it was "ActiveX.dll more
problems", I had basically the same problems. That's why I tried the
ActiveX.exe with separate thread.

Originally I used the Jungo code written expressly for VB2005. At that time
the best I could get was about 1.5 Heart beats per minute (a data burst
every 706 ms). That's when Jungo suggested I encapsulate the older USB
drivers in a VB6 ActiveX as the Net drivers were definitely slower.

I will read through the material you have given me but it doesn't look too
promising.

My thought is, if there was some way to transmit the address of the main
thread byte array to the separate thread, then the BurstData event would
only have to deliver a flag. The separate thread would have already put the
data in the main thread byte array.

Comments?

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:PXGEFzznGHA.4632@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Thank you for the source code.
>
> I've gone through the code and also done some research on the COM Interop
> performance.
>
> Based on my research, the bottleneck should be the BurstData event raised
> from VB6. I've created some test projects to benchmark the difference
> between VB6 and VB2005 handling the event. Handling the event in VB2005 is
> much slower than in VB6. This is difficult to overcome due to the nature
> of
> marshaling between COM and .NET.
>
> After I reviewed the source code of the ActiveX DLL project, I think it's
> possible to implement it in VB2005 using P/Invoke to call the USB device
> APIs. Also, thread is supported in VB2005 natively.
>
> Although P/Invoke still has some overhead, it's much faster than COM
> Interop. Please see following documentation for more information on
> Managed/Unmanaged Code Interoperability:
>
> #An Overview of Managed/Unmanaged Code Interoperability
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/ht
> ml/manunmancode.asp
> This article provides basic facts about interoperability between managed
> and unmanaged code, and guidelines and common practices for accessing and
> wrapping unmanaged API from managed code and for exposing managed APIs to
> unmanaged callers. Security and reliability considerations, performance
> data, and general practices for development processes are also
> highlighted.
>
> With every transition from managed code to unmanaged code (and vice
> versa),
> there is some performance overhead. The amount of overhead depends on the
> types of parameters used. The CLR interop layer uses three levels of
> interop call optimization based on transition type and parameter types:
> just-in-time (JIT) inlining, compiled assembly stubs, and interpreted
> marshaling stubs (in order of fastest to slowest type of call).
>
> Approximate overhead for a platform invoke call: 10 machine instructions
> (on an x86 processor).
>
> Approximate overhead for a COM interop call: 50 machine instructions (on
> an
> x86 processor).
>
>
> Here are some more resources on P/Invoke:
>
> #Platform Invoke Tutorial
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/
> vcwlkplatforminvoketutorial.asp
>
> #.NET: P/Invoke Revisited -- MSDN Magazine, October 2004
> http://msdn.microsoft.com/msdnmag/issues/04/10/NET/
> Talks about: Marshaling Structures, Object Lifetime and Pinning,
> Marshaling
> Value Types vs. Reference Types, StructLayoutAttribute, Non-Blittable
> Marshaling.
>
> #GotDotNet User Sample: Platform Invoke Samples
> http://www.gotdotnet.com/community/usersamples/details.aspx?sampleguid=f6f4c
> 339-22fd-44bb-a4fc-cfd874527ffb
> The platform invoke samples demonstrate how to call functions exported
> from
> an unmanaged library: how to declare different types, how to use available
> attributes to modify default behavior, how to use methods of the Marshal
> class when needed, and which aspects of garbage collection and threading
> could affect results.
>
> #GotDotNet User Sample: Interop Declarations for Windows.h
> http://www.gotdotnet.com/community/usersamples/details.aspx?sampleguid=f1dd7
> 0e4-c212-4a6f-bff7-c82e34c8836f
> When a Win32 API is not exposed by the .NET framework you must manually
> write an interop wrapper to access that API. Writing these wrappers is
> difficult and error prone. This post includes C# definitions of many
> common
> Win32APIs and their related data structures
>
> #pinvoke.net: the interop wiki!
> http://www.pinvoke.net
> PINVOKE.NET attempts to address the difficulty of calling Win32 or other
> unmanaged APIs in managed code (languages such as C# and VB.NET). This
> site
> is a repository where you can find, edit, and add PInvoke signatures,
> user-defined types. Think of this as the 21st century version of VB6's
> "API
> Text Viewer".
>
> Hope this helps. Please feel free to post here if anything is unclear.
>
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
5 Jul 2006 9:13 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your update.

I've checked your previous posts about this issue and seen more clearly
now.

Based on my test, even if the BurstData event is not passing the byte
array, the performance is still much worse. I think one possible solution
is to use windows message to pass the data between VB6 and VB2005.

1) In VB6 ActiveX DLL, add following declarations:

Private Const WM_COPYDATA = &H4A

Private Type COPYDATASTRUCT
    dwData As Long
    cbData As Long
    lpData As Long
End Type

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long

2) Change class CMain to let the VB2005 client pass in a window handle,
this will be used to send the message WM_COPYDATA back to.

Public Sub SendData(ByVal hwnd As Long, ByVal data() As Byte)
    Dim cds As COPYDATASTRUCT
    cds.cbData = ubound(data) - lbound(data) + 1
    cds.lpData = VarPtr(data(0))
    SendMessage ByVal hwnd, WM_COPYDATA, ByVal hwnd, cds
End Sub

3) In VB2005, overrides a WinForm's WndProc event to handle the WM_COPYDATA
message:

Private Const WM_COPYDATA As Integer = &H4A

<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.
LayoutKind.Sequential)> _
Private Structure COPYDATASTRUCT
    Public dwData As IntPtr
    Public cbData As Integer
    Public lpData As Integer
End Structure

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If m.Msg = WM_COPYDATA Then
        Dim cds As COPYDATASTRUCT = New COPYDATASTRUCT()
        cds =
System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam,
cds.GetType())
        If (cds.cbData > 0) Then
            Dim data(cds.cbData - 1) As Byte
            Dim source As IntPtr = New IntPtr(cds.lpData)
            Dim length As Integer = cds.cbData
            System.Runtime.InteropServices.Marshal.Copy(source, data, 0,
length)
        End If
    End If
    MyBase.WndProc(m)
End Sub

4) At last, you pass "Me.Handle" in VB2005 WinForm to VB6 as the window
handle.

Hope this helps. Please feel free to post here if anything is unclear.


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
5 Jul 2006 2:47 PM
Galen Somerville
Whew!

I'll give this a try and get back to you.

Thanks

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:J3SDKNBoGHA.4188@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Thank you for your update.
>
> I've checked your previous posts about this issue and seen more clearly
> now.
>
> Based on my test, even if the BurstData event is not passing the byte
> array, the performance is still much worse. I think one possible solution
> is to use windows message to pass the data between VB6 and VB2005.
>
> 1) In VB6 ActiveX DLL, add following declarations:
>
> Private Const WM_COPYDATA = &H4A
>
> Private Type COPYDATASTRUCT
>    dwData As Long
>    cbData As Long
>    lpData As Long
> End Type
>
> Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
> (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
> Any) As Long
>
> 2) Change class CMain to let the VB2005 client pass in a window handle,
> this will be used to send the message WM_COPYDATA back to.
>
> Public Sub SendData(ByVal hwnd As Long, ByVal data() As Byte)
>    Dim cds As COPYDATASTRUCT
>    cds.cbData = ubound(data) - lbound(data) + 1
>    cds.lpData = VarPtr(data(0))
>    SendMessage ByVal hwnd, WM_COPYDATA, ByVal hwnd, cds
> End Sub
>
> 3) In VB2005, overrides a WinForm's WndProc event to handle the
> WM_COPYDATA
> message:
>
> Private Const WM_COPYDATA As Integer = &H4A
>
> <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.
> LayoutKind.Sequential)> _
> Private Structure COPYDATASTRUCT
>    Public dwData As IntPtr
>    Public cbData As Integer
>    Public lpData As Integer
> End Structure
>
> Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
>    If m.Msg = WM_COPYDATA Then
>        Dim cds As COPYDATASTRUCT = New COPYDATASTRUCT()
>        cds =
> System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam,
> cds.GetType())
>        If (cds.cbData > 0) Then
>            Dim data(cds.cbData - 1) As Byte
>            Dim source As IntPtr = New IntPtr(cds.lpData)
>            Dim length As Integer = cds.cbData
>            System.Runtime.InteropServices.Marshal.Copy(source, data, 0,
> length)
>        End If
>    End If
>    MyBase.WndProc(m)
> End Sub
>
> 4) At last, you pass "Me.Handle" in VB2005 WinForm to VB6 as the window
> handle.
>
> Hope this helps. Please feel free to post here if anything is unclear.
>
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
5 Jul 2006 8:28 PM
Galen Somerville
Well I must have done something wrong. After the thread in CThread is
started and ThreadWait is True, the USB device creates the sounds (at 75
beats per minute) and you can hear them in the loudspeaker.

I break after the sound create command is given and before the ThreadWait is
set to False. The sounds coming out of the speaker are real slow, like 1
beat per minute. Blows my mind. Here's my code changes:

In the VB6 code the only call to SendData is in the CallBackForm routine
which is only used when CThread is active.

In the module starting the action I added:
     MyUSB.WinHandle = frmSweep.Handle

This is frmSweep. Note that GD_StatError is still used
    Private WithEvents GD As HeartBeat.CMain
    Private Const WM_COPYDATA As Integer = &H4A
    <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>
_
    Private Structure COPYDATASTRUCT
        Public dwData As IntPtr
        Public cbData As Integer
        Public lpData As Integer
    End Structure

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = WM_COPYDATA Then
            Dim cds As COPYDATASTRUCT = New COPYDATASTRUCT()
            cds =
System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, _
                cds.GetType())
            If (cds.cbData > 0) Then
                '                Dim data(cds.cbData - 1) As Byte
                Dim source As IntPtr = New IntPtr(cds.lpData)
                Dim length As Integer = cds.cbData
                System.Runtime.InteropServices.Marshal.Copy(source, _
                    ModUSB.bytAry, 0, length)
            End If
        End If
        MyBase.WndProc(m)
        ModUSB.dtStatus = 0
        modMain.USBflag = True
    End Sub

    '   Private Sub GD_BurstData(ByRef DatAry As System.Array) Handles
GD.BurstData
    '       ModUSB.bytAry = DatAry
    '       ModUSB.dtStatus = 0
    '       modMain.USBflag = True
    '   End Sub

    Private Sub GD_StatError(ByRef Stat As Integer) Handles GD.StatError
        ModUSB.dtStatus = Stat
        modMain.USBflag = True
    End Sub


This is in Cmain. Note that the CThread still sends message to CMain and the
Shared module
has: Public gHwnd As Long

Const WM_COPYDATA = &H4A

Public Event StatError(Stat As Long)

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As
Any, PSrc As Any, ByVal ByteLen As Long)
Private Type COPYDATASTRUCT
    dwData As Long
    cbData As Long
    lpData As Long
End Type
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long

Private TI As ThreadInfo, SharedArr() As ThreadData
Private LastRingIndex As Long
Private WithEvents CallbackForm As fCallBackTrigger
Private DeviceForm As fCallBackTrigger

Public Sub SendData(ByVal hWnd As Long, ByRef data() As Byte)
Dim cds As COPYDATASTRUCT
    cds.cbData = UBound(data) - LBound(data) + 1
    cds.lpData = VarPtr(data(0))
    SendMessage ByVal hWnd, WM_COPYDATA, ByVal hWnd, cds
End Sub

Private Sub CallbackForm_CheckRingBufferQueue() 'Callback from our invisible
Helper-Form ("Event-Pumping" as necessary)
Dim DataChunk As TBurstData
  With SharedArr(0)
    If .Stat = 0 Then
        'let's catch up all the Buffers we've missed since our last check
        'the Ringbuffer has slots for 64 "SixPacks" - so you we can buffer
        'single delays of up to around 1 Sec inside the Event-Handling
        Do While LastRingIndex <> .RingIndex
            LastRingIndex = (LastRingIndex + 1) Mod (UBound(.RingBuffer) +
1) 'move one slot forward
            DataChunk = .RingBuffer(LastRingIndex) 'let's make a copy from
the slot...
            SendData gHwnd, DataChunk.DatAry
        Loop
    Else
        Stat = .Stat
        RaiseEvent StatError(Stat)
    End If
    End With
End Sub

Public Property Let WinHandle(ByVal value As Long)
    gHwnd = value
End Property

Galen


Show quoteHide quote
"Galen Somerville" <galen@community.nospam> wrote in message
news:e4FTEIEoGHA.4332@TK2MSFTNGP03.phx.gbl...
> Whew!
>
> I'll give this a try and get back to you.
>
> Thanks
>
> Galen
>
> "Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
> news:J3SDKNBoGHA.4188@TK2MSFTNGXA01.phx.gbl...
>> Hi Galen,
>>
>> Thank you for your update.
>>
>> I've checked your previous posts about this issue and seen more clearly
>> now.
>>
>> Based on my test, even if the BurstData event is not passing the byte
>> array, the performance is still much worse. I think one possible solution
>> is to use windows message to pass the data between VB6 and VB2005.
>>
>> 1) In VB6 ActiveX DLL, add following declarations:
>>
>> Private Const WM_COPYDATA = &H4A
>>
>> Private Type COPYDATASTRUCT
>>    dwData As Long
>>    cbData As Long
>>    lpData As Long
>> End Type
>>
>> Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
>> (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
>> Any) As Long
>>
>> 2) Change class CMain to let the VB2005 client pass in a window handle,
>> this will be used to send the message WM_COPYDATA back to.
>>
>> Public Sub SendData(ByVal hwnd As Long, ByVal data() As Byte)
>>    Dim cds As COPYDATASTRUCT
>>    cds.cbData = ubound(data) - lbound(data) + 1
>>    cds.lpData = VarPtr(data(0))
>>    SendMessage ByVal hwnd, WM_COPYDATA, ByVal hwnd, cds
>> End Sub
>>
>> 3) In VB2005, overrides a WinForm's WndProc event to handle the
>> WM_COPYDATA
>> message:
>>
>> Private Const WM_COPYDATA As Integer = &H4A
>>
>> <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.
>> LayoutKind.Sequential)> _
>> Private Structure COPYDATASTRUCT
>>    Public dwData As IntPtr
>>    Public cbData As Integer
>>    Public lpData As Integer
>> End Structure
>>
>> Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
>>    If m.Msg = WM_COPYDATA Then
>>        Dim cds As COPYDATASTRUCT = New COPYDATASTRUCT()
>>        cds =
>> System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam,
>> cds.GetType())
>>        If (cds.cbData > 0) Then
>>            Dim data(cds.cbData - 1) As Byte
>>            Dim source As IntPtr = New IntPtr(cds.lpData)
>>            Dim length As Integer = cds.cbData
>>            System.Runtime.InteropServices.Marshal.Copy(source, data, 0,
>> length)
>>        End If
>>    End If
>>    MyBase.WndProc(m)
>> End Sub
>>
>> 4) At last, you pass "Me.Handle" in VB2005 WinForm to VB6 as the window
>> handle.
>>
>> Hope this helps. Please feel free to post here if anything is unclear.
>>
>>
>> Regards,
>> Walter Wang (waw***@online.microsoft.com, remove 'online.')
>> Microsoft Online Community Support
>>
>> ==================================================
>> When responding to posts, please "Reply to Group" via your newsreader so
>> that others may learn and benefit from your issue.
>> ==================================================
>>
>> This posting is provided "AS IS" with no warranties, and confers no
>> rights.
>>
>
>
Author
6 Jul 2006 10:56 AM
Walter Wang [MSFT]
Hi Glen,

Thank you for your update.

This is a quick note to let you know that I am performing research on this
issue and will get back to you as soon as possible. I appreciate your
patience.

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
6 Jul 2006 2:25 PM
Galen Somerville
I should have mentioned, the CThread has started but the ThreadWait is True
so no messages are sent from CThread.

Yet in the App the Event is taking place. This should not happen until
ThreadWait is made False.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:OyoiNrOoGHA.2024@TK2MSFTNGXA01.phx.gbl...
> Hi Glen,
>
> Thank you for your update.
>
> This is a quick note to let you know that I am performing research on this
> issue and will get back to you as soon as possible. I appreciate your
> patience.
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
7 Jul 2006 6:31 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your update.

I'm currently working on another possible solution using Memory Map File
and Win32 Event to exchange data between unmanaged and managed code. While
I'm working on this, I have a suggestion and need your help:

Since CreateThread uses Free threading model, and Visual Basic 6.0 only
supports Apartment-model threading model, using CreateThread here may not
be appropriate. You can refer to http://support.microsoft.com/kb/198607/
for more information. I recommend you remove CThread, merge its function
into CMain, and create CMain in a new thread from VB2005. Thus in CMain we
only need to periodically read from the USB device and send message back to
VB2005 main window. Also, you don't need to use the form "fCallBackTrigger"
anymore; you can now enable the "Unattended Execution" and "Retained in
Memory" options in VB6 project's properties. You must turn on the
"Unattended Execution" option and the "Retained in Memory" option before
compilation to host a VB 6.0 component (ActiveX DLL) in a multi-threaded
environment. See http://support.microsoft.com/kb/307211/ for more
information.

Other related KB articles:

#PRB: Threading Issues with Visual Basic 6.0 ActiveX Components
http://support.microsoft.com/kb/241896/

Please kindly test this workaround and let me know the result. Thanks!


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
7 Jul 2006 5:49 PM
Galen Somerville
Cannot merge CThread with CMain.

I originally had the Jungo calls in VB2005 directly like the following:
    dwstatus = WDU_TransferBulk(gDev, 2, False, 0, VarPtr(bytAry(Loc)), _
        ByVal Blen, Xsfrd, ByVal Twait)
But the marshaling took to long. It's still mashaled to Cmain but the call
is shorter like:
    Call BulkOut(bytAry, Blen , dwstatus)
The performance this way is acceptable.

There are hundreds of IN/Out calls to Cmain but only one call to CThread

I could remove CThread and it's support from the dll. Then create a second
dll with the CThread stuff in it.

Would that suffice for this new test?

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:H%23If47YoGHA.2024@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Thank you for your update.
>
> I'm currently working on another possible solution using Memory Map File
> and Win32 Event to exchange data between unmanaged and managed code. While
> I'm working on this, I have a suggestion and need your help:
>
> Since CreateThread uses Free threading model, and Visual Basic 6.0 only
> supports Apartment-model threading model, using CreateThread here may not
> be appropriate. You can refer to http://support.microsoft.com/kb/198607/
> for more information. I recommend you remove CThread, merge its function
> into CMain, and create CMain in a new thread from VB2005. Thus in CMain we
> only need to periodically read from the USB device and send message back
> to
> VB2005 main window. Also, you don't need to use the form
> "fCallBackTrigger"
> anymore; you can now enable the "Unattended Execution" and "Retained in
> Memory" options in VB6 project's properties. You must turn on the
> "Unattended Execution" option and the "Retained in Memory" option before
> compilation to host a VB 6.0 component (ActiveX DLL) in a multi-threaded
> environment. See http://support.microsoft.com/kb/307211/ for more
> information.
>
> Other related KB articles:
>
> #PRB: Threading Issues with Visual Basic 6.0 ActiveX Components
> http://support.microsoft.com/kb/241896/
>
> Please kindly test this workaround and let me know the result. Thanks!
>
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
8 Jul 2006 8:25 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your update.

What I mean is removing multi-threading code and the callback form from
VB6. I agree with you than we may not simply merge CThread with CMain here.
Based on my understanding, CThread is used to continually send burst data
back to UI, CMain is used to communicate with the USB device since directly
call USB device APIs in VB2005 is slow, right? If it's possible, I
recommend we separate CMain and CThread, and create CThread from a separate
thread in VB2005.

--
Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
9 Jul 2006 1:41 AM
Galen Somerville
We are now together on this. I will try your suggestions and get back to
you.

Thanks

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:OvRAPgmoGHA.4208@TK2MSFTNGP04.phx.gbl...
> Hi Galen,
>
> Thank you for your update.
>
> What I mean is removing multi-threading code and the callback form from
> VB6. I agree with you than we may not simply merge CThread with CMain
> here. Based on my understanding, CThread is used to continually send burst
> data back to UI, CMain is used to communicate with the USB device since
> directly call USB device APIs in VB2005 is slow, right? If it's possible,
> I recommend we separate CMain and CThread, and create CThread from a
> separate thread in VB2005.
>
> --
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
14 Jul 2006 1:08 PM
Walter Wang [MSFT]
Hi Galen,

I am interested in this issue. Would you mind letting me know the result of
the suggestions? If you need further assistance, feel free to let me know.
I will be more than happy to be of assistance.

Have a great day!

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
14 Jul 2006 2:47 PM
Galen Somerville
Show quote Hide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:iaSxha0pGHA.5976@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> I am interested in this issue. Would you mind letting me know the result
> of
> the suggestions? If you need further assistance, feel free to let me know.
> I will be more than happy to be of assistance.
>
> Have a great day!
>
> Regards,
> Walter Wang (waw***@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>

I have split the dll's so Cmain works with main thread and CThread is in
it's own ActiveX.dll.

In my limited time I have looked at BackgroundWorker in the Help pages but
find no examples of tying this to a dll.

On my web site http://home.surewest.net/galen/download/download.html is
USBdrvr.zip which contains the CThread class dll.

I use the name MyUSB for the Cmain stuff and I thought I would use MyWrkr
for the CThread stuff.

How do I create that MyWrkr and make it a separate thread?

Galen
Author
17 Jul 2006 3:46 AM
Walter Wang [MSFT]
Hi Galen,

Thank you for your update.

Since we're trying to use Windows message to send back the data, I think
using a simple thread would be enough for our purpose.

We need to create a simple class to represent the parameters needs to pass
to the worker thread, I've created a simple method that needs three
parameters:

<vb6>

Public Sub DoWork(ByVal hwnd As Long, ByVal count As Long, ByVal delay As
Long)
    Dim b(20) As Byte
    Dim cds As COPYDATASTRUCT
    Dim i As Long

    For i = LBound(b) To UBound(b)
        b(i) = i
    Next

    For i = 0 To count - 1
        cds.cbData = 10
        cds.lpData = VarPtr(b(0))
        SendMessage ByVal hwnd, WM_COPYDATA, ByVal hwnd, cds
        Sleep delay
    Next
End Sub


<VB2005>

    Public Class WorkerArgs
        Public hwnd As IntPtr
        Public count As Integer
        Public delay As Integer

        Public Sub New(ByVal h As IntPtr, ByVal c As Integer, ByVal d As
Integer)
            hwnd = h
            count = c
            delay = d
        End Sub
    End Class

Then we use ParameterizedThreadStart to start this new thread:

<VB2005>

    Dim worker As New vbworker.Class1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
        Dim t As Thread = New Thread(New ParameterizedThreadStart(AddressOf
DoWork))
        t.Start(New WorkerArgs(Me.Handle, 10000, 1))
    End Sub

    Private Sub DoWork(ByVal arg As Object)
        Dim wa As WorkerArgs = CType(arg, WorkerArgs)
        worker.DoWork(wa.hwnd, wa.count, wa.delay)
    End Sub

Hope this helps. Please feel free to post here if anything is unclear.

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
20 Jul 2006 10:19 AM
Walter Wang [MSFT]
Hi Galen,

Since this thread is going rather long, to accelerate the process, you can
email me if you like. I'll be glad to continue working on this with you.
Thanks.

Have a nice day!

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.