|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Re: ActiveX raise event - attn Walter WangTalk 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 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. 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. > 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. 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. > 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. >> > > 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. 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. > 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. >> > > 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. 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. > 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. 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. > 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. >> > > 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. 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. 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 [attached file: capture.jpg]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. > 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. 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. > > 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. 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. > 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. >> > > 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.
Selecting a single node in 'XML'
Constants can't be defined in a namespace. WTH? Math class for Visual Basic.NET (matrix operations) Graph control webreq.getresponse exceptions Application.StartupPath turn off assertions in VB 2005 Adding a Web Reference into a Windows Project Errors in Page directive Determine if xml is malformed |
|||||||||||||||||||||||