Home All Groups Group Topic Archive Search About

Re: ActiveX raise event - attn Walter Wang

Author
29 Oct 2006 12:51 AM
Galen Somerville
Talk about delayed replies, this is from Aug 1,2006

I am having problems figuring out how to modify your "data transmitter" to
fit the "WD_transferInterrupt" call that I have to use.

On my web site at http://home.surewest.net/galen/download/download.html are
both your data transmitter "VB2005_filemapping.zip" and my VB6 data
transmitter "HeartBeat.zip".

In the HeartBeat class are some Let's and Gets that are required. In
addition the base module has the declares for the WD_transferinterrupt call.

I ran your demo and like you said, it runs fast.

I would appreciate it if you could give this a quick look.

Galen

Author
30 Oct 2006 7:10 AM
Walter Wang [MSFT]
Hi Galen,

Welcome back.

To incorporate the changes into your project, I think you need to first
understand the background of inter-process communication and
synchronization.

My sample code is using two Event objects and a shared file mapping to
synchronize and share data between the VB6 and VB2005 process. Please
briefly take a look at following MSDN documentation:

#CreateEvent(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCTSTR) function
http://msdn.microsoft.com/library/en-us/dllproc/base/createevent.asp?frame=t
rue
Multiple processes can have handles of the same event object, enabling use
of the object for interprocess synchronization.

#Event Objects
http://msdn.microsoft.com/library/en-us/dllproc/base/event_objects.asp?frame
=true
An event object is a synchronization object whose state can be explicitly
set to signaled by use of the SetEvent function.

#Interprocess Synchronization
http://msdn.microsoft.com/library/en-us/dllproc/base/interprocess_synchroniz
ation.asp?frame=true

#CreateFileMapping (6 Parameters) function [Base]
http://msdn.microsoft.com/library/en-us/memory/base/createfilemapping.asp?fr
ame=true

#Creating Named Shared Memory [Base]
http://msdn.microsoft.com/library/en-us/memory/base/creating_named_shared_me
mory.asp?frame=true
To share data, multiple processes can use memory-mapped files that the
system paging file stores.

The principle should be easy to understand. The Transmitter class (in VB6)
will first wait for the Receiver (in VB2005) when it's ready, then write to
the shared file mapping for the data, after the data is written, signal the
Receiver that the data is ready to read. For the Receiver, it will create a
separate thread to do the similar waiting and reading using the same Event
objects--but with different order.

Based on my understanding, the WD_transferinterrupt method you mentioned is
used to read the data from the underlying hardware in VB6. I think you
could call this in the Transmitter.Transmit method:
1) Read data from hardware
2) Wait for Receiver ready
3) Write to shared file mapping
4) Signal the Receiver that the data is ready to read
5) goto step 1)

For the Receiver, you should be able to use it directly in your project.

Let me know if this helps.
Author
30 Oct 2006 5:36 PM
Galen Somerville
Thanks Walter

I think I'm close to solving it. In the receiver I'll probably change the
While to a For-Next as I call WD_Transfer a specific number of times then
stop.

Will do some reading.

Later

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:pB1l%23J$%23GHA.1976@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Welcome back.
>
> To incorporate the changes into your project, I think you need to first
> understand the background of inter-process communication and
> synchronization.
>
> My sample code is using two Event objects and a shared file mapping to
> synchronize and share data between the VB6 and VB2005 process. Please
> briefly take a look at following MSDN documentation:
>
> #CreateEvent(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCTSTR) function
> http://msdn.microsoft.com/library/en-us/dllproc/base/createevent.asp?frame=t
> rue
> Multiple processes can have handles of the same event object, enabling use
> of the object for interprocess synchronization.
>
> #Event Objects
> http://msdn.microsoft.com/library/en-us/dllproc/base/event_objects.asp?frame
> =true
> An event object is a synchronization object whose state can be explicitly
> set to signaled by use of the SetEvent function.
>
> #Interprocess Synchronization
> http://msdn.microsoft.com/library/en-us/dllproc/base/interprocess_synchroniz
> ation.asp?frame=true
>
> #CreateFileMapping (6 Parameters) function [Base]
> http://msdn.microsoft.com/library/en-us/memory/base/createfilemapping.asp?fr
> ame=true
>
> #Creating Named Shared Memory [Base]
> http://msdn.microsoft.com/library/en-us/memory/base/creating_named_shared_me
> mory.asp?frame=true
> To share data, multiple processes can use memory-mapped files that the
> system paging file stores.
>
> The principle should be easy to understand. The Transmitter class (in VB6)
> will first wait for the Receiver (in VB2005) when it's ready, then write
> to
> the shared file mapping for the data, after the data is written, signal
> the
> Receiver that the data is ready to read. For the Receiver, it will create
> a
> separate thread to do the similar waiting and reading using the same Event
> objects--but with different order.
>
> Based on my understanding, the WD_transferinterrupt method you mentioned
> is
> used to read the data from the underlying hardware in VB6. I think you
> could call this in the Transmitter.Transmit method:
> 1) Read data from hardware
> 2) Wait for Receiver ready
> 3) Write to shared file mapping
> 4) Signal the Receiver that the data is ready to read
> 5) goto step 1)
>
> For the Receiver, you should be able to use it directly in your project.
>
> Let me know if this helps.
>
Author
2 Nov 2006 9:26 AM
Walter Wang [MSFT]
Hi Galen,

How is it going?

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
2 Nov 2006 5:31 PM
Galen Somerville
Pretty good (I think).

Got problems using a MASM dll where it gives me a protected memory warning.

More later.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:3xAh6Dm$GHA.5920@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> How is it going?
>
> 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 Nov 2006 9:32 PM
Galen Somerville
Replaced all masm dll references with appropriate BitConverter stuff.
Program runs but I get an error 13 plus it displays maybe 12 pixels on
screen then data receiver must catch an exception and stops at "Throw"

It appears the error 13 is coming from the HeartBeat.exe which means their
is a type mismatch somewhere.

I made a number of changes (really additions) to your code. Check my web
site for HeartBeat.zip and DataReceiver.zip

My main problem is that once I start the data receiver, etc, it has to stay
there after a full screen batch of data is captured. After a slight pause,
it is going to capture another batch of data and so forth. This continues
until the user stops the sweeps in one of several ways.

I already see that I have to move the "Buffer_Ready" to a different point in
the calling program. It cannot be sent after each increment of data is
received. It has to be sent just before a full screen of data is received
then turned off until time for next batch of full data.

If you see anything glaringly wrong, please let me know.

Thanks
Galen



Show quoteHide quote
"Galen Somerville" <galen@community.nospam> wrote in message
news:O3Ylg0q$GHA.4024@TK2MSFTNGP04.phx.gbl...
> Pretty good (I think).
>
> Got problems using a MASM dll where it gives me a protected memory
> warning.
>
> More later.
>
> Galen
>
> "Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
> news:3xAh6Dm$GHA.5920@TK2MSFTNGXA01.phx.gbl...
>> Hi Galen,
>>
>> How is it going?
>>
>> 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 Nov 2006 11:08 AM
Walter Wang [MSFT]
Hi Galen,

If the error is from your vb6 process (heartbeat.exe), then it will not be
passed to your vb2005 process because we're using memory mapping to pass
the data, not remote method invocation.

I might not fully understand what you meant: "it has to stay there after a
full screen batch of data is capture...". If you want your receiver paused
after some data, I think you can add a synchronized property to notify the
thread that is capturing data:

        Private m_bPaused As Boolean
        Public Property Paused() As Boolean
            Get
                SyncLock (m_SyncRoot)
                    Return m_bPaused
                End SyncLock
            End Get
            Set(ByVal value As Boolean)
                SyncLock (m_SyncRoot)
                    m_bPaused = value
                End SyncLock
            End Set
        End Property

and you check this flag in the Capture():

                While (True)
                    If Paused Then
                        Threading.Thread.Sleep(100)
                    Else
                        SetEvent(m_AckEvent)
            ...

Since the event is not set when Paused, the transmitter will also block and
wait until un-Paused.

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 Nov 2006 3:47 PM
Galen Somerville
I will try the Paused method.

Assuming a 1,024 x 768 screen. Because of 6 sets of samples the display
screen will be 1,020 pixels wide. So we collect 170 sets of data with each
set being 24 bytes.

Assume 2.9 Heart beats are displayed across the screen. When that display is
finished the program checks to see if data collection should stop. If not
the program loops until the USB returns a flag that the next trigger point
has been found.

Now the next 1,020 pixels worth of data is processed and the whole thing
repeats.

When waiting for the next trigger, a whole heart beat could go by.

So the pause is the period where we wait for the next batch of 1,020 pixels
of data.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:35gi2PZAHHA.5200@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> If the error is from your vb6 process (heartbeat.exe), then it will not be
> passed to your vb2005 process because we're using memory mapping to pass
> the data, not remote method invocation.
>
> I might not fully understand what you meant: "it has to stay there after a
> full screen batch of data is capture...". If you want your receiver paused
> after some data, I think you can add a synchronized property to notify the
> thread that is capturing data:
>
>        Private m_bPaused As Boolean
>        Public Property Paused() As Boolean
>            Get
>                SyncLock (m_SyncRoot)
>                    Return m_bPaused
>                End SyncLock
>            End Get
>            Set(ByVal value As Boolean)
>                SyncLock (m_SyncRoot)
>                    m_bPaused = value
>                End SyncLock
>            End Set
>        End Property
>
> and you check this flag in the Capture():
>
>                While (True)
>                    If Paused Then
>                        Threading.Thread.Sleep(100)
>                    Else
>                        SetEvent(m_AckEvent)
> ...
>
> Since the event is not set when Paused, the transmitter will also block
> and
> wait until un-Paused.
>
> 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 Nov 2006 8:14 PM
Galen Somerville
My VB6 process always comes up with a type mismatch
msgbox. This means it
has stopped processing data.

The VB2005 capture process always fails with an array
problem. When I set a
breakpoint where it is going to get the memory mapped
data, the array is
always zero size.

I'm wondering if the VB6 fails because the Events are
Longs with non-zero
meaning signalled. Whereas the VB2005 Events are using
intptr members. ??

Galen


Show quoteHide quote
"Galen Somerville" <galen@community.nospam> wrote in
message news:uuvzBIeAHHA.5068@TK2MSFTNGP02.phx.gbl...
>I will try the Paused method.
>
> Assuming a 1,024 x 768 screen. Because of 6 sets of
> samples the display screen will be 1,020 pixels wide.
> So we collect 170 sets of data with each set being 24
> bytes.
>
> Assume 2.9 Heart beats are displayed across the
> screen. When that display is finished the program
> checks to see if data collection should stop. If not
> the program loops until the USB returns a flag that
> the next trigger point has been found.
>
> Now the next 1,020 pixels worth of data is processed
> and the whole thing repeats.
>
> When waiting for the next trigger, a whole heart beat
> could go by.
>
> So the pause is the period where we wait for the next
> batch of 1,020 pixels of data.
>
> Galen
>
> "Walter Wang [MSFT]" <waw***@online.microsoft.com>
> wrote in message
> news:35gi2PZAHHA.5200@TK2MSFTNGXA01.phx.gbl...
>> Hi Galen,
>>
>> If the error is from your vb6 process
>> (heartbeat.exe), then it will not be
>> passed to your vb2005 process because we're using
>> memory mapping to pass
>> the data, not remote method invocation.
>>
>> I might not fully understand what you meant: "it has
>> to stay there after a
>> full screen batch of data is capture...". If you want
>> your receiver paused
>> after some data, I think you can add a synchronized
>> property to notify the
>> thread that is capturing data:
>>
>>        Private m_bPaused As Boolean
>>        Public Property Paused() As Boolean
>>            Get
>>                SyncLock (m_SyncRoot)
>>                    Return m_bPaused
>>                End SyncLock
>>            End Get
>>            Set(ByVal value As Boolean)
>>                SyncLock (m_SyncRoot)
>>                    m_bPaused = value
>>                End SyncLock
>>            End Set
>>        End Property
>>
>> and you check this flag in the Capture():
>>
>>                While (True)
>>                    If Paused Then
>>                        Threading.Thread.Sleep(100)
>>                    Else
>>                        SetEvent(m_AckEvent)
>> ...
>>
>> Since the event is not set when Paused, the
>> transmitter will also block and
>> wait until un-Paused.
>>
>> 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 Nov 2006 3:29 AM
Walter Wang [MSFT]
Hi Galen,

Since I don't know about how your hardware calling interface worked, I
cannot provide accurate information on where might be wrong. However, from
your code:

Stat = WDU_TransferInterrupt(gDev, 129, True, 0, VarPtr(DatAry(0)), Quant,
Xsfrd, Twait)

I do see that you're passing a global byte array's pointer to the function,
make sure you have initialized the array and have plenty size for the read
data. Also, after that, you need to check the array size before sending
data out. For demonstrate purpose, I didn't put that check in the
Transmitter.Transmit() method. You might need to check do that there or
before calling Transmit().


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
13 Dec 2006 2:53 AM
Galen Somerville
Well, like a bad penny I show up again. Much VB6 maintenance work the last
month and a half.

The DataReceiver code and the full HeartBeat.exe code is on my web site at
http://home.surewest.net/galen/download/download.html

Basically the mapped memory seems to be in trouble. In the Capture routine
the arySize always turns up zero.

        Private Sub Capture()
            On Error GoTo ErrHandler
AGAIN:
            If Paused Then
                Threading.Thread.Sleep(2)
            Else
                SetEvent(m_AckEvent)
                Dim ret As Integer

                If m_StatEvent <> IntPtr.Zero Then
                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
                    Dim data(arrSize - 1) As Byte
                    Dim i As Integer
                    For i = 0 To 3
                        data(i) = Marshal.ReadByte(New
IntPtr(m_SharedMem.ToInt32() + i + 4))
                    Next

I know the HeartBeat.exe is running. The code on my web site shows the
MsgBox messages I used for testing. The arguments from Process.Start have
the correct values.

Here is how the main program starts up the whole process.

    Public Sub SimBegin()
        Dim intTmp As Short, Quan As Short
        Dim NewProcess As Process = New Process
        Dim DatRcvr As New Utility.DataReceiver
        Quan = gParam.NumSmps * 2
        ReDim bytAry(Quan - 1)
        If gblnUSB Then
            MyUSB.ThreadBytes = Quan
            MyUSB.LoopCount = gScreen.HorPixels / 6
            Process.Start("E:\Wang\oleVB6\HeartBeat.exe", CStr(hDev) & " " &
CStr(MyUSB.LenTime) _
                & " " & CStr(MyUSB.ThreadBytes) & " " &
CStr(MyUSB.LoopCount))
            AddHandler DatRcvr.OnData, AddressOf DatRcvr_OnData
            AddHandler DatRcvr.OnTimeout, AddressOf DatRcvr_OnTimeout
            DatRcvr.Paused = True
            DatRcvr.Start("HeartBeat", CInt(MyUSB.ThreadBytes)) 'start
capturing
        End If
        DSBFlg = True 'DSB and ASB
        frmSweep.FrameFlt.Visible = False
        gblnExtActive = False
        frmSweep.KeyPreview = True
HRTBEG:
        ReDim gbytEPC(1)
        gbytEPC(0) = Asc(":")
        gbytEPC(1) = 5
        Call DoCmdWthAck(2)
        If ErrFlg Then GoTo HRTERR
        DSBFlg = False

HRTAGN:
        If Not gblnDisPhono Then GoTo NODISP
        Call ChkForTrigger()
        If ErrFlg Then GoTo ENDDISP
        If Not gLect.Active Then frmSweep.CmdBut(6).Enabled = True
        ErrFlg = False
        If gblnUSB Then
            DatRcvr.Paused = False
        End If
        ReDim gbytEPC(1)
        gbytEPC(0) = Asc(":")
        gbytEPC(1) = 21 'start sounds
        Call DoCmdDirect(2)
        If ErrFlg Then GoTo HRTERR
        Application.DoEvents()
        If CmdButIndex = 9 Then GoTo HRTEND
        GoTo HRTRDY

NODISP:
        Application.DoEvents()
        If CmdButIndex <> 10 Then GoTo ENDDISP
        If RateIncFlg Or RateDecFlg Then GoTo ENDDISP
        GoTo NODISP

HRTRDY:
        SwpButNum = 10
        If gbytSwpdir = 0 Then
            Call LeftRight(frmSweep.PictDraw)
            If ErrFlg Then GoTo HRTEND
        Else
            Call RightLeft(frmSweep.PictDraw)
            If ErrFlg Then GoTo HRTEND
        End If
ENDDISP:
        If gblnUSB Then DatRcvr.Paused = True 'stop capturing
        If CmdButIndex = 9 Then GoTo HRTEND

My real concern is that the DataReceiver is a separate thread. This just
adds more overhead. The HeartBeat should just raise events in the main
program and handle the data there.

Basically the USB device sets the data rate. The HeartBeat thread
interrogates the USB with a finite timeout if data is late. This timeout
raises a failure event to shut things down. It also knows how many packets
to handle. After x number of packets it goes into a slow loop until notified
that more packets are due. So basically the HeartBeat thread is free
running.

When a data packet is received the DataReady event is raised. The main
program then asks HeartBeat for the data. This data is used to draw that
part of the traces to the screen. After drawing it waits for the next event.

If the events come faster than the main program can handle them, that
creates an error. So basically the main thread sits on it's butt until an
event is raised.

So the slowest rate is one that doesn't cause a HeartBeat timeout. The
fastest rate we can achieve is just below the rate where we handle all
events without overlap.

Whew

Galen


Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:rmckiYuAHHA.1984@TK2MSFTNGXA01.phx.gbl...
> Hi Galen,
>
> Since I don't know about how your hardware calling interface worked, I
> cannot provide accurate information on where might be wrong. However, from
> your code:
>
> Stat = WDU_TransferInterrupt(gDev, 129, True, 0, VarPtr(DatAry(0)), Quant,
> Xsfrd, Twait)
>
> I do see that you're passing a global byte array's pointer to the
> function,
> make sure you have initialized the array and have plenty size for the read
> data. Also, after that, you need to check the array size before sending
> data out. For demonstrate purpose, I didn't put that check in the
> Transmitter.Transmit() method. You might need to check do that there or
> before calling Transmit().
>
>
> 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
13 Dec 2006 7:52 AM
Walter Wang [MSFT]
Hi Galen,

You need to call WaitForSingleObject() to wait for the Transmitter to
notify you that the data is written to the shared memory before you call
Marshal.ReadIn32(m_SharedMem). Please refer to my initial version of
DataReceiver.vb for more information.

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
13 Dec 2006 4:35 PM
Galen Somerville
I'll go look for that.

I thought I used your code verbatim but something must have gone awry.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:PCSqguoHHHA.2080@TK2MSFTNGHUB02.phx.gbl...
> Hi Galen,
>
> You need to call WaitForSingleObject() to wait for the Transmitter to
> notify you that the data is written to the shared memory before you call
> Marshal.ReadIn32(m_SharedMem). Please refer to my initial version of
> DataReceiver.vb for more information.
>
> 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
13 Dec 2006 6:43 PM
Galen Somerville
WaitForSingleObject() is there but it sees that m_StatEvt is non-zero before
it gets to that point.

Out of curiosity, why do we need to WaitForSingleObject when the Transmitter
raises an event after it writes data to shared memory. If the Reciever were
idle and it recieved that event, wouldn't that suffice??

Galen


Show quoteHide quote
"Galen Somerville" <galen@community.nospam> wrote in message
news:OUtLpStHHHA.4804@TK2MSFTNGP03.phx.gbl...
> I'll go look for that.
>
> I thought I used your code verbatim but something must have gone awry.
>
> Galen
>
> "Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
> news:PCSqguoHHHA.2080@TK2MSFTNGHUB02.phx.gbl...
>> Hi Galen,
>>
>> You need to call WaitForSingleObject() to wait for the Transmitter to
>> notify you that the data is written to the shared memory before you call
>> Marshal.ReadIn32(m_SharedMem). Please refer to my initial version of
>> DataReceiver.vb for more information.
>>
>> 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 Dec 2006 4:48 AM
Walter Wang [MSFT]
Hi Galen,

From your version of the DataReceiver.vb, I can see you added two another
events m_statEvent and m_stopEvent, what's them for?

Here's your code:

                If m_StatEvent <> IntPtr.Zero Then
                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
                    Dim data(arrSize - 1) As Byte
                    Dim i As Integer
                    For i = 0 To 3
                        data(i) = Marshal.ReadByte(New
IntPtr(m_SharedMem.ToInt32() + i + 4))
                    Next
                    RaiseEvent OnTimeout(data)
                    ResetEvent(m_AckEvent)
                    ResetEvent(m_StatEvent)
                Else

                    ret = WaitForSingleObject(m_ReadyEvent, INFINITE)

                    If (m_Capturer Is Nothing) Then Exit Sub

                    If (ret = WAIT_OBJECT_0) Then
                        Dim arrSize As Integer =
Marshal.ReadInt32(m_SharedMem)
                        Dim data(arrSize - 1) As Byte
                        Dim i As Integer
                        For i = 0 To arrSize - 1
                            data(i) = Marshal.ReadByte(New
IntPtr(m_SharedMem.ToInt32() + i + 4))
                        Next
                        RaiseEvent OnData(data)
                        ResetEvent(m_AckEvent)
                        ResetEvent(m_ReadyEvent)
                    End If
                End If

When you check "If m_StatEvent <> IntPtr.Zero Then", it's always true since
you've called CreateEvent for that. The code in the "else" part is my
original code, which first calls WaitForSingleObject. WaitForSingleObject
is used here to synchoronize the transmitter and receiver's code. Please
refer to the documentation I previously mentioned about Events,
inter-process communication. I will summarize some key points here:

1) When you call WaitForSingleObject on an event object, it will block
until the event is Set (by calling SetEvent, here the Transmitter will set
it after it wrote data to the shared memory).
2) After WaitForSingleObject returns and the return value is WAIT_OBJECT_0,
then we can be sure that the data is ready to read.

I will attach my original version of the code here again for your reference.

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 Dec 2006 4:51 AM
Walter Wang [MSFT]
After I reviewed the code again, I guess you're trying to add a time out to
the Receiver, right? If this is the case, you can change the second
parameter to WaitForSingleObject:

DWORD WINAPI WaitForSingleObject(
  HANDLE hHandle,
  DWORD dwMilliseconds
);


For testing purpose, I'm setting it to INFINITE which means waits for the
event for ever. You can set it to a reasonable number value and check the
return value with WAIT_TIMEOUT (&H00000102H) to see if it's timed out or
not.


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
15 Dec 2006 2:36 AM
Galen Somerville
I did a full restudy of the situation. This caused major code changes as
follows:

m_AckEvent and m_StopEvent are inputs to the DataTransmitter and are looked
at in the transmitter idle loop as WaitForSingleObject with Timeout as 0.

m_StopEvent, m_StatEvent and m_ReadyEvent are inputs to the DataReciever so
a WaitForMultipleObjects is used.

A m_StopEvent means that the DataTransmitter is shutting itself down.

A m_StatEvent means that a Timeout Status was generated by the USB call. The
status info will be presented to the main program by raising the TimeOut
event. Subsequently an m_StopEvent will be sent to shut down the
DataTransmitter.

A m_ReadyEvent means data from the USB is ready and will be presented to the
main program by raising the OnData event.

I searched for hours looking for VB.net code samples of
WaitForMultipleObjects and only found one. 90% of the samples were for C#
and C++.

I get an error on WaitForMultipleObjects as shown in the attached picture.

Below is snippets of code dealing with this:

        Private Declare Function WaitForMultipleObjects Lib "kernel32.dll"
(ByVal nCount As Integer _
            , ByVal lpHandles As IntPtr, ByVal bWaitAll As Boolean, ByVal
dwMilliseconds As Integer) As Integer

        Private h_EventAry(2) As IntPtr

                h_EventAry(0) = m_StopEvent
                h_EventAry(1) = m_StatEvent
                h_EventAry(2) = m_ReadyEvent

       Private Sub Capture()
            On Error GoTo ErrHandler
AGAIN:
            If Paused Then
                Threading.Thread.Sleep(2)
            Else
                If (m_Capturer Is Nothing) Then Exit Sub

                SetEvent(m_AckEvent)
                Dim ret As Integer
                ret = WaitForMultipleObjects(3, h_EventAry(0), False,
INFINITE)
                If ret = WAIT_FAILED Or ret = 0 Then    '0 = stop
                    Call Dispose()
                    Exit Sub
                End If
                If ret = 1 Then         '1 = Stat


Full code on my web site.

Galen

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:J765fwzHHHA.2024@TK2MSFTNGHUB02.phx.gbl...
> After I reviewed the code again, I guess you're trying to add a time out
> to
> the Receiver, right? If this is the case, you can change the second
> parameter to WaitForSingleObject:
>
> DWORD WINAPI WaitForSingleObject(
>  HANDLE hHandle,
>  DWORD dwMilliseconds
> );
>
>
> For testing purpose, I'm setting it to INFINITE which means waits for the
> event for ever. You can set it to a reasonable number value and check the
> return value with WAIT_TIMEOUT (&H00000102H) to see if it's timed out or
> not.
>
>
> 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.
>

[attached file: capture.jpg]
Author
18 Dec 2006 2:46 AM
Walter Wang [MSFT]
The second parameter to WaitForMultipleObjects should be an array of IntPtr:

   Private Declare Function WaitForMultipleObjects Lib "kernel32.dll"
(ByVal nCount As Integer _
            , ByVal lpHandles() As IntPtr, ByVal bWaitAll As Boolean, ByVal
dwMilliseconds As Integer) As Integer


   ...

   ret = WaitForMultipleObjects(3, h_EventAry, False, INFINITE)


You can find many useful p/invoke declarations at http://www.pinvoke.net


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
21 Dec 2006 2:17 AM
Galen Somerville
I changed to IntPtr just before I got your message. Almost working with one
major error as follows:

The HeartBeat.exe is compiled with Debug info. The program always fails in
the DataTransmitter when it goes to CopyMemory in the Failure sub.

I noticed that the shared memory had a different number for Recieiving and
transmitting as follows:

I changed the order so the data receiver gets set up first. The same thing
happens if I set up HeartBeat first.

            AddHandler DatRcvr.OnData, AddressOf DatRcvr_OnData
            AddHandler DatRcvr.OnTimeout, AddressOf DatRcvr_OnTimeout
            DatRcvr.Paused = True
            DatRcvr.Start("HeartBeat", CInt(MyUSB.ThreadBytes)) 'start
capturing
            MyUSB.ThreadBytes = Quan
            MyUSB.LoopCount = gScreen.HorPixels / 6
            '            Process.Start("HeartBeat.dll", CStr(hDev) & " " &
CStr(MyUSB.LenTime) _
            '                & " " & CStr(MyUSB.ThreadBytes) & " " &
CStr(MyUSB.LoopCount))
            Process.Start("E:\Wang\oleVB6\HeartBeat.exe", CStr(hDev) & " " &
CStr(MyUSB.LenTime) _
                & " " & CStr(MyUSB.ThreadBytes) & " " &
CStr(MyUSB.LoopCount))

Then I put a break just before m_Capturer is setup

                m_SharedFile = CreateFileMapping(New IntPtr(-1), sa,
PageProtection.ReadWrite, 0, _
                    MaxDataSize + 4, ChannelName + "_BUFFER")
                If (m_SharedFile = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create a
file mapping to slot " _
                        + ChannelName + "_BUFFER")
                End If

                m_SharedMem = MapViewOfFile(m_SharedFile, SECTION_MAP_READ,
0, 0, MaxDataSize + 4)
                If (m_SharedMem = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create a
mapping view for slot " + ChannelName + "_BUFFER")
                End If

                h_EventAry(0) = m_StopEvent
                h_EventAry(1) = m_StatEvent
                h_EventAry(2) = m_ReadyEvent

The value of m_SharedMem is 72155136

In the HeartBeat.exe I added a MsgBox to display arguments and hSharedMem

    hSharedFile = CreateFileMapping(-1, sa, 4, 0, Quant + 4, ChannelName &
"_BUFFER")
    hSharedMem = MapViewOfFile(hSharedFile, SECTION_MAP_WRITE, 0, 0, Quant +
4)
    ResetEvent hEventAck
    ResetEvent hEventData
    ResetEvent hEventStat
    ResetEvent hEventStop
    MsgBox CmdString & "   " & hSharedMem

The value of hSharedMem is 13893632. The other arguments are correct.

As a side note, the data array
    ReDim DatAry(Quant - 1)

In the Failure sub
    Dim lb As Long: lb = LBound(DatAry)
    Dim ub As Long: ub = UBound(DatAry)
    Dim size As Long: size = ub - lb + 1
    CopyMemory ByVal hSharedMem, size, 4

has an upper bound of 0 and a lower bound of 4206800 when I select Break on
the Debug error message.

Galen



Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:PUdox6kIHHA.516@TK2MSFTNGHUB02.phx.gbl...
> The second parameter to WaitForMultipleObjects should be an array of
> IntPtr:
>
>   Private Declare Function WaitForMultipleObjects Lib "kernel32.dll"
> (ByVal nCount As Integer _
>            , ByVal lpHandles() As IntPtr, ByVal bWaitAll As Boolean, ByVal
> dwMilliseconds As Integer) As Integer
>
>
>   ...
>
>   ret = WaitForMultipleObjects(3, h_EventAry, False, INFINITE)
>
>
> You can find many useful p/invoke declarations at http://www.pinvoke.net
>
>
> 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
24 Dec 2006 3:01 AM
Walter Wang [MSFT]
Although two processes are using the same named file mapping, the memory
address will not be necessarily the same; therefore I think the issue
you're seeing is correct.

What's the exact error you're seeing?

I understand that you're adding new features to your program constantly,
however, please do make sure the basic one works as you expected before
adding more new features. This way, you could easily find out which part of
the code is causing the problem.

Merry Christmas and Happy New Year!

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
25 Dec 2006 5:07 PM
Galen Somerville
I'm not adding new features. I'm changing existing features to fit the
sequence of events.

Currently the HeartBeat.exe uses WaitForMultipleObjects for events "Stop"
and "Ack" in that order. these are the only incoming events and cannot use
SingleObject as either event may come in.

The same is true for the DataReciever. The two events "Stat" and "Ready" may
be recieved in any order. So WaitForMultipleObjects must be used.

The current Error occurs when the DataReceiver calls WaitForMultipleObjects.
the error is:
Error #-2147467261. Attempted to read or write protected memory.

The pertinent changes to your code follows. I think the declarations of the
events and the EventAry are in trouble but I can only find C# code examples.

Galen

Declares
        Private Declare Function WaitForMultipleObjects Lib "kernel32.dll"
(ByVal nCount As Integer _
            , ByVal lpHandles As IntPtr, ByVal bWaitAll As Boolean, ByVal
dwMilliseconds As Integer) As Integer

        Private m_ReadyEvent As IntPtr = IntPtr.Zero
        Private m_StatEvent As IntPtr = IntPtr.Zero
        Private h_EventAry(1) As IntPtr

Sub Initialize
                m_ReadyEvent = CreateEvent(sa, False, False, ChannelName +
"_DATA_READY")
                If (m_ReadyEvent = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create event
" + ChannelName + "_DATA_READY")
                End If

                m_StatEvent = CreateEvent(sa, False, False, ChannelName +
"_STAT_FAIL")
                If (m_StatEvent = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create event
" + ChannelName + "_STAT_FAIL")
                End If

                h_EventAry(0) = m_StatEvent
                h_EventAry(1) = m_ReadyEvent

Sub Capture
                Dim ret As Integer
Error here      ret = WaitForMultipleObjects(2, h_EventAry(0), False,
INFINITE)
                If ret = WAIT_FAILED Then
                    Call CloseEXE()
                    Call Dispose()
                    Exit Sub
                End If
                If ret = 0 Then         '0 = Stat
                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
                    Dim data(arrSize - 1) As Byte
                    Dim i As Integer
                    For i = 0 To 3
                        data(i) = Marshal.ReadByte(New
IntPtr(m_SharedMem.ToInt32() + i + 4))
                    Next
                    RaiseEvent OnTimeout(data)
                    ResetEvent(m_StatEvent)
                    Call Dispose()
                    Exit Sub
                Else
                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
                    Dim data(arrSize - 1) As Byte
                    Dim i As Integer
                    For i = 0 To arrSize - 1
                        data(i) = Marshal.ReadByte(New
IntPtr(m_SharedMem.ToInt32() + i + 4))
                    Next
                    RaiseEvent OnData(data)
                    ResetEvent(m_AckEvent)      '????
                    ResetEvent(m_ReadyEvent)
                End If
            End If

Show quoteHide quote
"Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
news:Nq8tjfwJHHA.4020@TK2MSFTNGHUB02.phx.gbl...
> Although two processes are using the same named file mapping, the memory
> address will not be necessarily the same; therefore I think the issue
> you're seeing is correct.
>
> What's the exact error you're seeing?
>
> I understand that you're adding new features to your program constantly,
> however, please do make sure the basic one works as you expected before
> adding more new features. This way, you could easily find out which part
> of
> the code is causing the problem.
>
> Merry Christmas and Happy New Year!
>
> 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
26 Dec 2006 4:44 PM
Galen Somerville
I fixed the problem by getting rid of the Stat and Ready event variables and
using the EventAry directly. Code show below.

So now it runs but I am receiving an error message from the Transmitter
which has to do with the call to the USB device.
The correct USB devicce number is recieved by the Transmitter but the error
says "Device not found"

Shared memory working fine. The error number from Transmitter is sent to the
Reciever as 68093584 via the Stat Event and the main program inteprets this
number mean "Device not found"

Thanks for all of the help on this project. Now I have to work with Jungo on
the USB problem.

Galen

Code changes
        Private h_EventAry(1) As IntPtr

                h_EventAry(1) = CreateEvent(sa, False, False, ChannelName +
"_DATA_READY")
                If (h_EventAry(1) = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create event
" + ChannelName + "_DATA_READY")
                End If

                h_EventAry(0) = CreateEvent(sa, False, False, ChannelName +
"_STAT_FAIL")
                If (h_EventAry(0) = IntPtr.Zero) Then
                    Throw CreateApplicationException("Failed to create event
" + ChannelName + "_STAT_FAIL")
                End If

                ret = WaitForMultipleObjects(2, h_EventAry(0), False,
INFINITE)


Show quoteHide quote
"Galen Somerville" <galen@community.nospam> wrote in message
news:OF3RacEKHHA.420@TK2MSFTNGP06.phx.gbl...
> I'm not adding new features. I'm changing existing features to fit the
> sequence of events.
>
> Currently the HeartBeat.exe uses WaitForMultipleObjects for events "Stop"
> and "Ack" in that order. these are the only incoming events and cannot use
> SingleObject as either event may come in.
>
> The same is true for the DataReciever. The two events "Stat" and "Ready"
> may be recieved in any order. So WaitForMultipleObjects must be used.
>
> The current Error occurs when the DataReceiver calls
> WaitForMultipleObjects. the error is:
> Error #-2147467261. Attempted to read or write protected memory.
>
> The pertinent changes to your code follows. I think the declarations of
> the events and the EventAry are in trouble but I can only find C# code
> examples.
>
> Galen
>
> Declares
>        Private Declare Function WaitForMultipleObjects Lib "kernel32.dll"
> (ByVal nCount As Integer _
>            , ByVal lpHandles As IntPtr, ByVal bWaitAll As Boolean, ByVal
> dwMilliseconds As Integer) As Integer
>
>        Private m_ReadyEvent As IntPtr = IntPtr.Zero
>        Private m_StatEvent As IntPtr = IntPtr.Zero
>        Private h_EventAry(1) As IntPtr
>
> Sub Initialize
>                m_ReadyEvent = CreateEvent(sa, False, False, ChannelName +
> "_DATA_READY")
>                If (m_ReadyEvent = IntPtr.Zero) Then
>                    Throw CreateApplicationException("Failed to create
> event " + ChannelName + "_DATA_READY")
>                End If
>
>                m_StatEvent = CreateEvent(sa, False, False, ChannelName +
> "_STAT_FAIL")
>                If (m_StatEvent = IntPtr.Zero) Then
>                    Throw CreateApplicationException("Failed to create
> event " + ChannelName + "_STAT_FAIL")
>                End If
>
>                h_EventAry(0) = m_StatEvent
>                h_EventAry(1) = m_ReadyEvent
>
> Sub Capture
>                Dim ret As Integer
> Error here      ret = WaitForMultipleObjects(2, h_EventAry(0), False,
> INFINITE)
>                If ret = WAIT_FAILED Then
>                    Call CloseEXE()
>                    Call Dispose()
>                    Exit Sub
>                End If
>                If ret = 0 Then         '0 = Stat
>                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
>                    Dim data(arrSize - 1) As Byte
>                    Dim i As Integer
>                    For i = 0 To 3
>                        data(i) = Marshal.ReadByte(New
> IntPtr(m_SharedMem.ToInt32() + i + 4))
>                    Next
>                    RaiseEvent OnTimeout(data)
>                    ResetEvent(m_StatEvent)
>                    Call Dispose()
>                    Exit Sub
>                Else
>                    Dim arrSize As Integer = Marshal.ReadInt32(m_SharedMem)
>                    Dim data(arrSize - 1) As Byte
>                    Dim i As Integer
>                    For i = 0 To arrSize - 1
>                        data(i) = Marshal.ReadByte(New
> IntPtr(m_SharedMem.ToInt32() + i + 4))
>                    Next
>                    RaiseEvent OnData(data)
>                    ResetEvent(m_AckEvent)      '????
>                    ResetEvent(m_ReadyEvent)
>                End If
>            End If
>
> "Walter Wang [MSFT]" <waw***@online.microsoft.com> wrote in message
> news:Nq8tjfwJHHA.4020@TK2MSFTNGHUB02.phx.gbl...
>> Although two processes are using the same named file mapping, the memory
>> address will not be necessarily the same; therefore I think the issue
>> you're seeing is correct.
>>
>> What's the exact error you're seeing?
>>
>> I understand that you're adding new features to your program constantly,
>> however, please do make sure the basic one works as you expected before
>> adding more new features. This way, you could easily find out which part
>> of
>> the code is causing the problem.
>>
>> Merry Christmas and Happy New Year!
>>
>> 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
27 Dec 2006 6:15 AM
Walter Wang [MSFT]
Galen,

Thanks for the update. Glad to know that you've fixed the shared memory
problem. I hope you could solve the USB device problem soon.

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.