|
-
Aug 21st, 2001, 06:24 PM
#1
Thread Starter
Addicted Member
Async Serial
I desire to have an object that I can use within VB that will provide asynchronous serial features (i.e. it will generate some sort of event when data arrives, and so forth).
Now, the Microsoft’s MSCOMM control does provide me with this data arrival event. However, I can't seem to use this control without seating the OCX (putting it on a form). Is there any way I can access this object without seating it? This may be one option.
The other option is to access the port through API - this is what MSCOMM does anyways. Thus, calls to CreateFile, GetCommState, etc, etc. It seems that to provide Async this way I have to use CreateFile with it's Async functionality. All is good ... It appears I will end up needing multiple threads such that one thread can be 'waiting' for data to arrive and the main thread can still be responsive to the client process. Is this all true or have I gone mad? HeHe.
These appear to be my options?
-
Aug 21st, 2001, 06:40 PM
#2
Frenzied Member
Since the easiest method is the MSComm Control I have to ask - what is wrong with "seating the ocx on the form"? You don't see it when the program runs.
I don't understand this statement,
"It appears I will end up needing multiple threads such that one thread can be 'waiting' for data to arrive and the main thread can still be responsive to the client process"
As far as I know only one "thing" can have access to a Com Port at a time. What exactly would the other thread be doing.
Greg
Free VB Add-In - The Reference Librarian
Click Here for screen shot and download link.
-
Aug 21st, 2001, 08:09 PM
#3
Thread Starter
Addicted Member
HeHe. I love your curiosity.
My response to your question of "seating" is that sometimes a form or other seat is not available. For instance, if I create a DLL.
A DLL has no 'default' place to seat the MSCOMM control. Although, I could create a seat for it. Ultimately, I don't like this approach because it has too many 'layers' and it appears inefficient.)
So let's just accept that I don't have a seat, and go from there.
There still may be a way to use MSCOMM here, but I haven't figured it out yet? I don't see why I can't?
You said ...
""As far as I know only one "thing" can have access to a Com Port at a time.""
When you call CreateFile you are given a handle. This handle can, if allowed, be used by other threads.
You said ...
""What exactly would the other thread be doing.""
It appears that, even if you want async access, one way or the other, ultimately, some thread ends up in a 'wait'. (This is simply how the OS operates.)
OK. So if you only have one thread and it's waiting, then your client (interface) stalls. The Buttons on the Form don't respond, etc - you know what I mean.
Seemingly, once this is accepted...
If the server thread is waiting, how can it now respond to the client's requests - it would be 'unresponsive'.
This is where, I believe, a multiple wait is utilized.
First, I will need a multiple use object. This will be my 'standard interface' between the real object and the (Automation) VB environment. This object really only so that the client doesn't have to make (know about) API calls (in VB) - I can just call the object's Public Sub.
Second, I will need a single use (each has it's own thread). It will wait for both serial activity (OS File Handle) and (client) OS Events.
Is this making sense to anyone? Please note that you will likely require significant serial and / or VB/OS knowledge to comment.
-
Aug 21st, 2001, 09:28 PM
#4
Frenzied Member
Yes, I do follow you to a certain degree. I don't understand your project, so my understanding only goes so far. The fact that you want to create a DLL that accesses com ports clears up perfectly why you do not want to rely on the ocx.
And the fact that you are concerned with "more layers" and the lack of effeciency with those layers also makes perfect sence as well. The last time I wrote a project that accessed com ports I went with the API instead of the VBX for just that reason. You may have guessed by now that the code was 16bit, so it will be usless to you. Microsoft changes com port access a lot from 16bit and 32bit, you didn't use "CreateFile".
I remember playing around with the new method of com port access when I first got VB4/32bit but dumped the whole mess for Winsock. I do find it interesting that you could have more than one thread have access to the same com port at the same time.
Again, going back to the OCX, it seems that its event driven nature would take care of the problem with waiting for something to happen. Although, I've written several VC++ dlls, my knowledge of using ocx created objects in them is non-existant.
My only suggetion now would be to have two apps. One would have access to the com port and the other woudl be taking care of the user. Of course, this idea is of no use if you want the com port access to be from a dll. However, if you do want to go that way I posted a sample project on my web site last week for someone that shows how to use SendMessage to reliably communicate between to apps using the WM_COPYDATA message.
SendMessage Example
Good luck.
Greg
Free VB Add-In - The Reference Librarian
Click Here for screen shot and download link.
-
Aug 21st, 2001, 11:18 PM
#5
Thread Starter
Addicted Member
All this threading for serial communication seems kinda ridiculous to me.
I have extensive pre-Windows experience in raw serial use (programming the UART chip and Interrupt Controller chip directly). In this case, your program can be doing whatever it wants (interacting with user) - UART serial events cause a hardware interrupt directly to your InterruptServiceRoutine. After service is complete, your main program resumes.
Actually, this can still be accomplished. However to keep with standardization and compatibility, it seems best to use the API.
I guess, in a sense, the ISR could be equivalent to a waiting thread. However, by specifics of definition, it is not - it's a chunk of code that you tell the CPU to execute when an interrupt is received. (No waiting thread here.)
Anyhow, thanks for your thoughts Greg.
-
Aug 22nd, 2001, 02:36 AM
#6
Fanatic Member
One way to get around it is to go Project, References, Browse, then drop the "Files of type" box to ActiveX Controls (OCX) and because it's (Mscomm32.ocx) compiled with a type library you can reference it without having to drop it on a form. You'll obviously still have to redist' the OCX, hope this helps...
Crispin
VB6 ENT SP5
VB.NET
W2K ADV SVR SP3
WWW.BLOCKSOFT.CO.UK
[Microsoft Basic: 1976-2001, RIP]
-
Aug 22nd, 2001, 02:18 PM
#7
Frenzied Member
Originally posted by Jay Rogozinsky
All this threading for serial communication seems kinda ridiculous to me.
I tend to agree. This is why I asked what that other thread would be doing in my first message.
Good luck,
Greg
Free VB Add-In - The Reference Librarian
Click Here for screen shot and download link.
-
Aug 22nd, 2001, 05:04 PM
#8
Thread Starter
Addicted Member
Thanks crispin I'll try that. I knew there must be a way to use it without seating it.
gdebacker: Yes, it still seems funny. However, it is the way to do things (now) - even MSCOMM uses multiple threads.
-
Aug 22nd, 2001, 05:24 PM
#9
Thread Starter
Addicted Member
I haven't done any actual IO, but, the port seemed to open.
crispin, I still have a question. Both of the following worked, which should I use and why:
Private WithEvents priMSCOMM As MSComm
Private WithEvents priMSCOMM As MSCommLib.MSComm
Am I simply being more explicit by saying MSCommLib, and, it is indeed MSCommLib that exposes the object MSComm? So it's the same thing, right?
-
Aug 23rd, 2001, 03:54 AM
#10
Fanatic Member
I always tend to use fully qualified ProgIDs (just habit), and I have a slightly unfounded (cause I don't have my book to hand)theory that when the COM calls (CoCreateInstance e.t.c) that get fired in the background instantiate the object, if they have the fully qualified ProgID, that they will make less calls to instantiate the right object, i.e.
Code:
Dim x As ADODB.Connection
Dim z As DAO.Connection
I can't find it right now, but in Ted Pattisons COM+ book, he goes into great detail about COM and object instantiation, and ProgIDs e.t.c e.t.c....
Bottom Line...
I do it mainly for readability and habit, but I also reckon it may be a "better practice" - but i'm open to other sugg's...
BTW: FWIW - I read that Strings chapter about five times, and I was quite startled as to the behind the scenes string jiggery pokery that VB does (it's awful isn't it) and I take back all my bloody minded comments - I'll be using Longs from now on
Crispin
VB6 ENT SP5
VB.NET
W2K ADV SVR SP3
WWW.BLOCKSOFT.CO.UK
[Microsoft Basic: 1976-2001, RIP]
-
Aug 23rd, 2001, 04:12 PM
#11
Thread Starter
Addicted Member
Thanks for looking into that call syntax. I too am in the habit of full qualification calls and such.
.....
We all make apparent silly comments sometimes. I believe I started it right before you did - my apologies.
I learned that Types could use String (in API calls). This I was not aware - VB will go through all that work in recreating a phantom type just to pass to the API - this can't be efficient and is certainly not portable.
-
Aug 24th, 2001, 01:08 PM
#12
Lively Member
even MSCOMM uses multiple threads...
There is a really great article on msdn that describes the whole multi-thread / sync v. async / overlapped v. non-overlapped issue. The article is a little dated, but most information is still good:
http://msdn.microsoft.com/library/de...sdn_serial.asp
Hope this helps with the debate about multiple threads...
-
Aug 24th, 2001, 01:22 PM
#13
Thread Starter
Addicted Member
Thanks Dave, I'll check that out.
-
Aug 25th, 2001, 11:16 AM
#14
Lively Member
Jay,
I'm currently coding a program which receives a datastream from a serial device (the program is a mapping program, receiving data from a gps), and the responsiveness of the user-interface is important to me as well. I've chosen to use API calls instead of mscomm (mostly because I'm an API freak)...that being said, I found a function which virtually eliminates the need to have a thread waiting for serial input (assuming your serial driver has a buffer...which i think most do?)
The cbInQue in the COMSTAT Type below actually tells you how many chars are in the input buffer. In my program, my gps sends approx. 0.7 seconds of data every two seconds. I run ClearCommError every 0.1 seconds to see if:
buffer size>0 and is the buffer size the same as it was 0.1 seconds ago.
If these criteria have been met, I assume the data burst from the gps is finished, and I run a ReadFile to get the buffered data.
The nice thing about the ClearCommError call is that there is essentially zero latency between the call and the return (i.e. it doesn't wait for the comm port to *do* something).
This has turned out to work beautifully for me...Just thought I'd share.
Declare Function ClearCommError Lib "kernel32" _
(ByVal hFile As Long, lpErrors As Long, _
lpStat As COMSTAT) As Long
Type COMSTAT
fBitFields As Long 'See Comment in Win32API.Txt
cbInQue As Long
cbOutQue As Long
End Type
*note: fBitFields gives you the ability to see if xon/xoff events have occured (if you're using flow control). Good description on MSDN or in the WIN32API.TXT file (IMHO this file is the second-greatest thing to happen to programming since the pointer)
-
Aug 25th, 2001, 02:43 PM
#15
Thread Starter
Addicted Member
Thanks for your help Dave.
I have already begun writing my serial interface.
However, I am choosing to use threads. I would almost do it (loop), but I am getting back valid data about every .05 seconds. I don't really like polling. Although, If I have serious problems doing what I want, I may take your suggestion.
I could use MSCOMM, but, I want to be sure I can control the situation (I have had issue with the MSCOMM before). Also, I am an API freak too - hehe.
You'll probably need some good parsing code. Let me know if you experience any problems with this. (One of my specialties.)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|