By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,707 Members | 1,605 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,707 IT Pros & Developers. It's quick & easy.

ActiveX.exe and RaiseEvent

P: n/a
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
Jun 29 '06 #1
Share this Question
Share on Google+
23 Replies


P: n/a
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?

Jun 29 '06 #2

P: n/a

"Chris Dunaway" <du******@gmail.com> wrote in message
news:11**********************@y41g2000cwy.googlegr oups.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
Jun 29 '06 #3

P: n/a

Galen Somerville wrote:
"Chris Dunaway" <du******@gmail.com> wrote in message
news:11**********************@y41g2000cwy.googlegr oups.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

Jun 29 '06 #4

P: n/a

"Chris Dunaway" <du******@gmail.com> wrote in message
news:11**********************@i40g2000cwc.googlegr oups.com...

Galen Somerville wrote:
"Chris Dunaway" <du******@gmail.com> wrote in message
news:11**********************@y41g2000cwy.googlegr oups.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
Jun 29 '06 #5

P: n/a
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 (wa****@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.

Jun 30 '06 #6

P: n/a
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

"Walter Wang [MSFT]" <wa****@online.microsoft.com> wrote in message
news:Vo**************@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 (wa****@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.

Jul 1 '06 #7

P: n/a
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 (wa****@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.

Jul 3 '06 #8

P: n/a

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:sy****************@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 (wa****@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
Jul 3 '06 #9

P: n/a
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/de...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/de...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/u...mpleguid=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/u...mpleguid=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 (wa****@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.

Jul 4 '06 #10

P: n/a
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

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:PX**************@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/de...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/de...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/u...mpleguid=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/u...mpleguid=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 (wa****@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.

Jul 4 '06 #11

P: n/a
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(Syste m.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.PtrToStruct ure(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 (wa****@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.

Jul 5 '06 #12

P: n/a
Whew!

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

Thanks

Galen

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:J3**************@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(Syste m.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.PtrToStruct ure(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 (wa****@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.

Jul 5 '06 #13

P: n/a
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(Syste m.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.PtrToStruct ure(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
"Galen Somerville" <ga***@community.nospamwrote in message
news:e4**************@TK2MSFTNGP03.phx.gbl...
Whew!

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

Thanks

Galen

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:J3**************@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(Syst em.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.PtrToStruc ture(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 (wa****@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.


Jul 5 '06 #14

P: n/a
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 (wa****@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.

Jul 6 '06 #15

P: n/a
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

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:Oy**************@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 (wa****@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.

Jul 6 '06 #16

P: n/a
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 (wa****@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.

Jul 7 '06 #17

P: n/a
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

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:H%****************@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 (wa****@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.

Jul 7 '06 #18

P: n/a
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 (wa****@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.
Jul 8 '06 #19

P: n/a
We are now together on this. I will try your suggestions and get back to
you.

Thanks

Galen

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:Ov**************@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 (wa****@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.

Jul 9 '06 #20

P: n/a
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 (wa****@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.

Jul 14 '06 #21

P: n/a

"Walter Wang [MSFT]" <wa****@online.microsoft.comwrote in message
news:ia**************@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 (wa****@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
Jul 14 '06 #22

P: n/a
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 (wa****@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.

Jul 17 '06 #23

P: n/a
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 (wa****@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.

Jul 20 '06 #24

This discussion thread is closed

Replies have been disabled for this discussion.