|
Answering the Phone with Phone Monitor Template
I tried to use the Phone Monitor and it causes a Run Time Error, something about "Cannot
Start MDI, no Application Active". Well, my program is certainly running, so what's the deal?
You are using the SDI, as opposed to, the MDI Interface. You cannot use Threads in an SDI
Application and the Phone Monitor needs to be started as a Thread.
The Phone Monitor needs to be able to open its own Window (with its own Accept Loop) so
that it can operate in the background. In order for this to work in Clarion, your Application
needs to use an "Application" Window as its Main Window. Threads in Clarion will
only work if your Main Window is an Application Window.
If your program only needs to display a Dialog Box, with no Child Windows, then the Phone
Monitor Template will not work, as written. What you can do, however, is copy the Source Code
from the Phone Monitor and paste it into your Application. Most of the work is performed in
the Timer Event.
Background File Transfers
Why don't the Upload and Download functions operate in the background?
Clarion is the only Application Generator that produces identical 16 and 32 Bit programs
with a simple click of the mouse. 16 Bit Clarion programs have always been able to use features
that other RAD environments can only implement in 32 bit programs.
Clarion uses the Accept Loop to accomplish much of its magic. In order for Background
Threads to operate, they must have an Accept Loop. This does not mean, however, that a Window
Procedure can enter into an Endless Loop and never check the Message Queue for Windows Messages.
In Clarion, Timer Events are used to implement Background Processing.
The File Transfer routines are written in "C", not in the Clarion Language. They
do not have a Clarion Window associated with them and hence do not have an Accept Loop. For
this reason, the Transfer routines must take control over your Clarion Program while a File
Transfer is in progress. If they didn't disable the Application Windows, your users would be
able to select Menu Items, but the Clarion Program would not respond because an Accept Loop
is not being Cycled.
Even if the Transfer Protocols were written in Clarion, they would have to use a Timer Event
in order to operate in the Background and this would not be acceptable since the transfer would
be horrendously slow.
It should be noted that the File Transfer routines do operate in the background,
to a certain extent. This is evident by the fact that you can move a Window on top of your
Application (while a transfer is taking place), move the Window away, and your Clarion Program
will repaint its Window. The Transfer routines were designed to allow the Clarion Program to
process its Messages.
In 32 Bit programs, CLACom Starts a Background Thread that does the actual File Transfer.
Background threads are being utilized, they just may not be apparent.
Checksums and CRC’s
I’m dealing with a device that sends a string of data followed by a Checksum Byte. Can I use
the CLACom CRC routines to compute this Checksum?
CRC’s are normally 2 or 4 bytes, whereas a Checksum is a single byte that is computed by
adding together the value of each character in a buffer. The high 8 bits are thrown away leaving
an 8 byte checksum.
Instead of simply adding the values together, some implementations Exclusive OR the values,
which offers slightly better error correction.
The following function can be used to compute a Checksum and with a slight modification,
an XOR Checksum. This example uses a CSTRING as the source of data since it is assumed you
will be working with data received from the Serial Port.
Prototype:
GetChecksum(*CSTRING),BYTE
Procedure:
GetChecksum FUNCTION(RStr)
Cnt SHORT
StrLen SHORT
Tally SHORT
ChkSum BYTE
CODE
Tally = 0
StrLen = Len(Clip(RStr))
! Tally up the Checksum
! Comment Out or Remove the Line inside
! the Loop that you do not need.
Loop Cnt = 1 to StrLen
! Compute a Regular Checksum
Tally += Val(RStr[Cnt])
! Compute an Exclusive OR Checksum
Tally = BXOR(Val(RStr[Cnt]),Tally)
End
ChkSum = Tally ! Checksum = lower 8 bits
Return(ChkSum)
CRC’s and GetCRC16()
When I use GetCRC16() to compute the 16 bit CRC value of a Data Buffer, the result doesn't
match the value that is received.
CLACom’s 16 bit CRC function utilizes the CRC-CCITT calculation (also known as the “Xmodem
CRC”). This is the function that is used to calculate a CRC for the Xmodem and Ymodem File
transfers in CLACom. The Polynomial is:
If your application requires the CRC-16 calculation that uses a Polynomial of:
a file containing the Clarion code that calculates this CRC is available in the Private
Download area for CLACom (the same place where you download the latest updates from).
If your application does use the CRC-CCITT Polynomial and GetCrc16() seems to be
returning the wrong value, you may need to reverse the Bytes in the return value from GetCRC16().
There is no standard as to how the 2 bytes of the CRC are sent (or received). Some implementations
send the Low order Byte first and some send the High order Byte first.
For the string 'TEXT', GetCRC16() returns 54512 or D4F0 hex. Reverse the Bytes and you have
F0D4 hex or 61652.
Example Code to reverse the Bytes.
CRC16 USHORT CRCVal USHORT CRCStr CSTRING(256)
CRCStr = 'TEST'
CRC16 = GetCRC16(CRCStr, 4)
! Reverse the Bytes
CRCVal = BSHIFT(CRC16, 8) + BSHIFT(CRC16,-8)
If you need access to the individual Bytes then use a GROUP as shown below.
CRCGRP GROUP LoByte BYTE HiByte BYTE END
CRC16 USHORT,OVER(CRCGRP) CRCVal USHORT CRCStr CSTRING(256)
CRCStr = 'TEST'
CRC16 = GetCRC16(CRCStr, 4)
! To reverse the bytes using the above GROUP
CRCVal = BSHIFT(CRCGRP.LoByte,8) + CRCGRP.HiByte
Clarion 5.x and 6 problems with Templates
I'm using Clarion 5.5. When I add a CLACom Template Procedure, such as InitializePort, the
procedure is empty and doesn't have a Window.
With Clarion 5.5 and above, you need to select the CLACom Template procedure from the Defaults
Tab on the Select Procedure Type window.
Clearing Strings and Buffers
I've written a routine that Dials a Phone Number. The Routine checks for CONNECT and BUSY strings
from the Modem. If it receives a BUSY string, it attempts to dial again. The problem is, on the
2nd and subsequent attempts, it always finds the word BUSY in the buffer. My routine
is clearing the CSTRING between each attempt to dial and it is also clearing the Receive Buffer.
Why is CLACom not clearing its buffers correctly?
You are probably using "String Slicing" or "Array Indexing", as opposed
to "String Concatenation", when storing Received Characters in your CSTRING buffer.
Since Slicing and Indexing are faster than using String Operations, this is the preferred method
of storing characters in a buffer. When clearing your String, you are no doubt using either
the Clear() function or setting the string to an empty string (myCString = '').
The Clear() function and setting a string to an empty string work correctly with Clarion
STRING's, however, they do not work as you might think with CSTRING's. With CSTRING's, Clarion
simply inserts a NULL (0) in the 1st character position. Any other characters in the string,
starting at position 2, are left intact.
If your Routine is not filtering out Carriage Returns and Line Feeds, these are being stored
in your String along with the word BUSY. The next time in to your Routine, you begin storing
Received Characters starting at position 1 (overwriting the NULL character and thus expanding
the String). The problem is, the word BUSY is still in the String! Your call to StrWord() is
finding the word BUSY and your Routine thinks that the Phone is Busy, when it actually is not.
CLACom includes a function called ClearVariable(). To use it, you pass the CSTRING variable,
a 0, and the number of bytes to clear. For instance: ClearVariable(myCString,0,20). This will
set the string to 20 Null's. Be careful that you do not attempt to clear more bytes than the
string's declared length or you will overwrite memory and cause a General Protection Fault
(GPF).
Compile Errors
I just downloaded the latest version of CLACom, and now when I compile my Application, I receive
errors saying that %WindowOperationMode and %IniSaveWindow are not defined.
We changed the Templates so that all of the Source Code is available in the Embeds. This
way if you need to change the functionality of a Template Procedure, you no longer have to
Edit the Template file. You can simply change the Embedded source code.
If you receive Compile Errors after Upgrading to a new version of CLACom, you should UnRegister
the CLACom Template, ReRegister it, and if you still receive compile errors, perform the following
steps:
If you are utilizing them, delete the PhoneMonitor, DialNumber and InitializePort Procedures.
They will become "todo" Procedures.
Once removed, you can then add the Template Procedures back in to your Application.
I just downloaded the latest version of CLACom, and now when I compile my Application, I receive
linker errors such as "Unresolved External _Func122@8 in Test001.obj".
There are two developer files, in addition to the CLACom32.DLL, that must remain
synchronized. These are:
- clacom.inc
- clacom32.lib
- clacom32.dll
If one or the other is out of sync, you will receive linker errors. Whenever you download
a new version or restore from a backup, be sure that you reference the 3 files from the same
release. For instance a version 5.0 clacom.inc will not work with a version 5.1 clacom32.lib.
Computer/Program Locks Up - No Device Attached
When I try to send data to the Serial Port and there is no Modem Attached or the Modem is turned
Off, the Computer Locks Up. (Note: this can also happen with any device, not just modems).
You no doubt have Hardware Flow Control (CTS/RTS) turned On (this is the default when calling
SetPort).
The "Lock-Up" you are experiencing is the Windows Communications Driver waiting
for the Clear To Send (CTS) Line to become active. This is occurring at the Device Driver level,
not in the CLACom Library.
If the Device doesn't use Hardware Handshaking (CTS/RTS) you can turn that off by using
either SetPortEx() or making a call to SetFlowControl() after calling SetPort(). You can also
check the Modem Status line after you call SetPort() and InitPort() to determine if the device
is attached and/or powered on.
Example:
! This has to be done after calling ! InitPort().
! This assumes that the device supports ! the CTS Line. If it doesn't, then you ! shouldn't be using CTS/RTS Flow Control.
modstat BYTE
modstat = ModemStat(ComPort)
If BAND(modstat, 010h) NOT= 010h ! Device is not hooked up or is not ! powered on. Display a message and ! tell user about situation. Don't ! send any data as Windows will hang End
It is up to the Application/Programmer to determine if a device is attached and/or turned
on. CLACom cannot do this for you since it only talks to Serial Ports, not devices that are
attached to those ports.
The ModemInstalled Template Procedure is provided so that you may check to see if a Modem
(or other Device that uses CTS Handshaking) is attached and powered on. The GTERM sample program
shows how to utilize this procedure.
Dialing and Working with Voice Lines
How do I dial a Phone Number that will not (or should not) have a Modem attached to it? My
Program has a DataBase of Contact Names and Phone Numbers. I need to allow the operator to Dial
a Number from this DataBase and tell the person to pick up the Handset when a person on the other
end answers the Phone. I don't want my modem to send any Carrier Signals, or otherwise make Modem
Noise.
For this task, you cannot use the DialNumber Template Procedure, since that routine expects
to connect with a remote modem.
Please see the Phone Dialer Application, available in the Software Library, for an example
program that demonstrates the techniques of working with Voice Modems.
Depending upon the capabilities of the Modem that is doing the Dialing, you have several
options. Basically, you simply use ModemPuts() to send the Dial String. Make sure there are
at least 2 tildes ('~') after the Dial String ('ATDT226-8033^M~~'). CLACom will send the Dial
String, and then wait 1 second before returning. Upon returning, the Modem will have Dialed
the Phone Number.
Now is where you run into problems and what you do from here on out is dependent upon the
Modem's capabilities.
The very basic approach is to tell the Operator to pick up the Phone, wait a second, and
then send a Carriage Return (ASCII 13) to the Modem to tell it to stop trying to Connect. But
what do you do if the Operator doesn't pick up the Phone in 1 second? By sending the Carriage
Return to the Modem, the Modem will release the line and stop trying to Connect. If the Operator
hasn't picked up an Extension Phone, the Line will be dropped and the Operator will receive
a Dial Tone. You could wait for 2 seconds before telling the Modem to drop the Line. This might
work, and gives the Operator 2 seconds to pick up the Handset. But then again, what if it takes
the Operator 3 seconds to pick up the Handset? 4 or 5 Seconds? If your program just blindly
sends a Carriage Return to tell the Modem to stop trying to connect, you've lost control over
the human intervention - the Operator using the program.
Generally, once you have sent a Dial String to the Modem, the Modem expects to wait 50 or
60 seconds for a Carrier from a Remote Modem. You can stop your Modem from waiting by sending
any character (normally a Carriage Return) to your Modem. If a Handset is not picked up after
the Modem has Dialed a Number, then the Modem will release the Line all by itself when it has
either Timed Out or you send a Carriage Return to it to tell it to abort the Call.
The Modem is only being used as an interface to the Phone System in order to send the DTMF
Dial Tones. Once the Modem has Dialed a Number, the Modem can be "released". However,
before releasing the modem, Somebody has to engage the Line by picking up an Extension Phone
to keep the line Open.
The best approach is to use Modems that return Call Progress status (i.e., BUSY, VOICE,
etc). When implementing an Automatic Dialer to do Sales Calls or any task where you are trying
to Dial a Human, as opposed to another Modem, what you should be most concerned with is the
"VOICE" response from the Modem. Not all Modems support a "VOICE" return
code. USRobotics Modems do, some Rockwell Chip Set Modems do, but most do not.
When using a Modem to Dial a Voice Number in order to get a Human on the other end, you
need to look for the word "VOICE" from your Modem. If you receive BUSY, CONNECT,
or you time out, there is no sense telling the Operator of your Program to pick up the Phone
and start talking.
Assuming you have a Modem (or block of Modems) that return the Result Code of "VOICE"
if a Human answers the Phone, then after sending the Dial String to Dial a Number, you need
to Monitor the incoming Serial Port Data Stream for the word "VOICE". You would "time
out" after 60 seconds if nothing comes in, and abort the call if CONNECT comes in (which
means you connected to another Modem), or you receive a "BUSY" string.
If your Modem does not return the "VOICE" Result Code, then simply Dial the Number,
tell the Operator to "Pick Up the Handset", and send a Carriage Return to the Modem
to tell it to Disconnect. Many programs provide an OK Button for the Operator to click on,
to tell the program that the Handset has been picked up (the program tells the Modem to drop
the Line only after the button has been pushed).
Also, have you noticed that extra Phone Jack on the back of the Modem? There should be 2
jacks. One labeled "Line" and one labeled "Phone". If you plug a Phone
into the "Phone Jack", and pick up the attached Phone after the Modem has dialed
a Number, the Modem should automatically release itself from the Phone Line. This is what this
jack is provided for.
Double Characters with Terminal in C5
After migrating my program to Clarion 5, the Terminal Emulator sends characters out the Com
Port twice.
C5 seems to be Peeking at its Messages as well as Retrieving them from the Message Queue.
This Peek and the Retrieve was causing problems for the Terminal Emulator because it needs
to take over the Clarion Message Loop in order to determine if a key was pressed (Clarion filters
the WM_CHAR messages that Windows sends to a program). This is the reason for the Double Characters
- the Hook Function that the Terminal uses was seeing the WM_CHAR message twice - once for
the Peek and once for the actual Retrieval by the Clarion Message Loop.
CLACom works around this problem and the Terminal Emulator works just fine with C5, but
if you've been working with a version of Clarion prior to version 5, you will need to reimport
the CLATERM.TXA file into your APP. This applies, even if you've downloaded a new version of
CLACom and are having the double character problem.
See the Help File to determine which TXA file you need to Import. Starting with version
4 of Clarion, there are 2 TXA files for Version 4 and Version 5 - one for the ABC Templates
and one for the Standard Templates (4 separate files that you can choose from - in addition
to the Version 2 TXA file!).
If you've modified the Terminal Emulator, the Quick Fix is as follows:
In the TermHookProc Terminal Procedure, replace this:
! Send a User Defined message that ! will slip thru
PostMessage(TermClientWin,EVENT:WM_CHAR, WMsg:wParam,WMsg:lParam)
with this:
! Send a User Defined message that ! will slip thru
If wParam = 1 PostMessage(TermClientWin,EVENT:WM_CHAR, WMsg:wParam,WMsg:lParam) End
Example Programs won't Compile
When I Compile any of the Example programs, I receive an error message saying that an Include
File cannot be found.
All Applications that utilize CLACom must include two files (Function Prototypes
and Global Variable declarations) as well as one Import Library. The Example programs
include these files, however the paths are relative to our Development Directory. You will
need to fix the Path to the 2 Include Files and the Import Library.
In the Global Application Embeds, select "Inside the Global Map", and change the
path to the CLACOM.INC file so that the file can be found during compile time. Do the same
for the CLACOMST.INC file in the "Global Data" Embed.
You will also need to edit the Project, delete the CLACom Import Library (CLACOMxx.LIB)
and then add it back in so that the Clarion Linker knows where to find it.
Hand Coders and Templates
I'm a Hand Coder and have never used the Application Generator. Will CLACom work for me since
I'm unable to use the Templates?
CLACom is written in "C" and interfaces to your Clarion Application as a DLL.
You are not required to use any of the Templates. They are simply provided to make certain
Communications Tasks a bit easier (such as Dialing a Phone Number, Answering the Phone, etc).
If you would like to use the prewritten Template code, you can easily copy the code from
the Template file and create your own Hand Written Procedures.
Hiding Windows
How do you hide a Window?
Create the Window with a Dimension of 1 by 1. Turn off all attributes so that Clarion doesn't
have a hard time dealing with the Window. After Opening the Window, or in the Open Window Event,
use Target{PROP:Hide}=1 to Hide the Window.
Long File Name Support
In my 32 bit Application, When I use the Terminal Emulator, it uses the Windows Explorer type
Dialog Boxes when you Open or Save a File. If I use the File Transfer routines directly in my
program (without the Terminal Emulator), they too, allow for Long File Names and use the Explorer
type Dialog Box.
However, when I use the Clarion FileDialog() Procedure, it uses the old 16 Bit File Open and
Save Dialog Boxes, and they just don't fit in with my 32 bit program. How is CLACom able to use
the Explorer type Dialog Boxes and Clarion can't? I really need to be able to utilize Long File
Names in my program.
Clarion needs to maintain compatibility with 16 bit programs. Because of this compatibility
issue, 32 bit programs are "stuck" with a 16 bit interface unless you directly call
the 32 bit WIN API functions.
CLACom provides Templates and Functions that you can use in your Application to utilize
Long File Names and the Explorer type File Open/Save Dialog Boxes. There is a Template procedure
called GetOpenSaveFile() that will allow you to prompt a user for a file to Open or Save As.
There is also a Control that you can use on your Windows that provides the standard "ellipses"
button. If a user clicks on the button, the Enhanced Explorer type File Open Dialog Box appears
instead of the dreaded 16 bit Dialog Box.
Note that starting with Version 4 of Clarion, the FileDialog() Procedure allows for Long
filenames and Enhanced Explorer type Dialog Boxes. If you haven't yet upgraded to Clarion 4
or 5, you might want to consider doing so.
NT Problems (Phone Monitor, DialNumber, IsCd, ModemStat)
I'm using the DialNumber Template Procedure to Dial into a Host system.
The number is dialed and I can tell by the Modem lights and the Host Screen that a Connection
has been established. However, DialNumber doesn't know that it is Connected and won't return control
back to the Procedure that called it.
Your program was, no doubt, compiled as a 16 bit EXE.
Windows NT barely tolerates 16 bit programs. If at all possible, they should not be used
under NT.
The problem you are experiencing is due to the fact that the 16 bit NT Comm Driver does
not support obtaining Modem Status. The 16 bit Comm API does not provide a means to obtain
Modem Status. Microsoft provides an undocumented workaround which works fine in Win 3.x and
Win 95/98. Apparently, however, Microsoft decided that Windows NT would not support this undocumented
method of obtaining Modem Status.
PhoneMonitor and DialNumber both make a call to IsCd to determine if a Carrier with a remote
modem has been established. IsCd, in turn, calls ModemStat to determine the current state of
the Modem Status Register. The Modem Status Register provides a Bit Map that allows you to
determine if there is a Carrier Signal. In a 16 bit program running under NT, ModemStat returns
0 which causes IsCd to return 0, which causes the Phone Monitor and DialNumber to fail to realize
that a Connection has been established.
The only solution is to use the 32 bit Comm Driver which requires that your program be compiled
as a 32 bit program using the 32 bit CLACom DLL.
Step By Step Instructions for Sending & Receiving Data
I've looked in the Manual and the On-Line Help Reference for a Step By Step Tutorial to help
me with using CLACom in my Clarion Program. I can't find any guidance to tell me what I need to
do to setup the port, initialize the Modem, Dial a Number, and then automatically send and receive
data and files.
Are there no Tutorials to read or Sample programs to look at?
CLACom includes a Sample Program called GTERM. In addition to an already compiled program,
you should find the source Applications for CFW 4 (ABC and Standard) and CFW 5 (ABC and Standard)
in your CLACom installation directory. In the Public Files area
of our Web Site you will also find many other example programs.
The CLACom Application Files contain a Wealth of Information. Nearly every line of Source
Code that was written to interface CLACom with the application is commented with meaningful
explanations. Most of the Communications Functionality in the GTERM Program comes from using
the Templates (DialNumber, Terminal, AnswerPhone, etc).
It is difficult to offer Step By Step Instructions, since we have no idea what it is you
wish to accomplish. You may wish to Dial a Number, Connect, and then send/receive a Credit
Card authorization. Others may wish to Connect, and then send/receive several files. Some need
to use the Serial Port to control a Robotic device (no modem attached, and precise control
over the data stream is necessary).
The Basic Steps are as follows:
We cannot possibly tell you what to do when it comes time to insert your own code to deal
with the Serial Port Data Stream. All we can do is offer advice and suggestions.
If you need Terminal Emulation capabilities, by all means start with the GTERM Sample program
as the "skeleton". Change the things you do not like and add your own features. All
that we require is that you remove our Logo and Name from the About Box and Splash Screen.
If you need to send and receive files automatically, download the Client/Server Sample Application
that is posted in the Software Library. It is fully commented and
very easy to change to suit your own needs.
If you need any help implementing CLACom with your Clarion Application, need advice, want
to know if it is better to use ComGetc() or ComGetd(), can't quite get that Modem to Dial,
or whatever problem you may be having, please feel free to send an email to support@gapdev.com,
and we will offer all the help we can. We would prefer E-Mail as opposed to Voice Calls on
such issues because that allows us to send you snippets of code, and gives others an opportunity
to share in the exchange of information.
Universal Serial Bus (USB) Devices
Does CLACom work with USB Devices?
CLACom works with USB Serial Devices such as Modems and Serial Printers, or any Device where
the USB Port on the Device is the equivalent to a Serial Port.
Keep in mind that CLACom only talks to Serial Devices via the Windows Communications API.
It knows nothing about the Physical Devices that you attach to a Serial or USB Port.
The USB Device will install a Device Driver that supplements the Windows Communications
Driver. A USB Modem Driver, for instance, will add a Phantom Serial Port such as COM 3 or COM
4. You would then use this Serial Port when communicating with the Device.
Version Number of CLACom
How do I determine what version I have?
The most reliable method is to right click on the CLACOM32.DLL file and select Properties.
On the Version Tab you will find the Compile Date and Version Number.
Alternatively, the File Modification Date on any of the DLL files should show a Date and
Time that represents the Compile Date and the Version Number.
WaitForString doesn't work in Terminal Emulator
I'm using the Terminal Emulator to provide access to a Support BBS. I want to automate the
log on process using WaitForString. It isn't working. WaitForString always "times out",
and I know for a fact that the Host is sending the String that I'm waiting for.
The Terminal Emulator turns on Receive Notification to its Client Window. This means that
the Terminal Window Procedure will always get first stab at any incoming characters. In 16
Bits, Windows sends a Notification message directly to the Window Procedure. In 32 Bits, CLACom
starts a Background Thread that waits for Communications Events. When a character is received,
this Thread sends a Notification message to the Window Procedure.
WaitForString will never "see" any characters while the Terminal Window is active.
This is because the Terminal Procedure has already removed the characters from the Receive
Buffer.
All is not lost however. You can temporarily disable Receive Notification to the Terminal
Window, wait for a String to arrive, send your Response, and then re-enable Receive Notification.
This is similar to what the File Transfer routines do, since they need to have access to
the Receive Buffer.
If AutoLogOn ! Don't let Terminal have any ! Characters until we have logged on
CLATermPrepareTransfer(CLATermPort,0)
! Wait for User ID Prompt
! If String doesn't Arrive ! Display an Error Message ! and Close the Terminal Window
If WaitForString(AppWin,CLATermPort,'USER ID',20) Do NobodyHome Post(Event:CloseWindow) Else ! We received the Log On Prompt ! Now send the User Id
TmpCString = 'MyUserID^M' ModemPuts(CLATermPort, TmpCString)
! Clear any remaining characters
ClrRecvBuf(CLATermPort)
! Re-Enable Notification Thread
CLATermPrepareTransfer(CLATermPort,1) End End
Working with 2 or more Ports at the same time
I'm trying to send and receive data over 2 Serial Ports at the same time. The problem is, while
I'm working with one port, the other port seems to be put on hold until I'm finished processing
the data from the first port. I made sure to Start() the 2 Procedures so that they can both run
at the same time.
To simultaneously monitor and process data on 2 or more Serial Ports, you need to use the
Timer Event and process data in "chunks". Both of your "started" Procedures
need to have a Window associated with them. This is because you need to do your work inside
of an Accept Loop. The Windows, themselves, can be hidden if you have no need to display data.
In order for other Threads to run, you must CYCLE the Accept Loop. You do this by "falling
through" to the End of the Accept Loop or by issuing an explicit Cycle command. If you
need to import 100 or 1000 records that were received over the Serial Port, into a Database,
no other Thread will run until you are finished importing the records. In 16 Bit Windows, no
other Windows Program will run until you are finished.
The following is an Example of how things were done in DOS programs:
Set(MyDataBase)
Loop Next(MyDataBase)
If ErrorCode() Break End End
If there are 1000 records to process, the Loop would not terminate until an Error occurs
or EOF is reached. If it takes 10 minutes to process the records, nobody cared, because your
program is the only program running.
In Windows, things are quite a bit different. Your program most likely is not the only program
running. Remember, you've got Windows itself running, perhaps a Clock, and perhaps a Word Processing
program. If you use the above Loop in a Windows Program, and it takes 10 minutes to process
the records, your Program will be non-responsive to Windows Events for 10 minutes. Move another
Window on top of your Application, and then move the other Window away, and your Application
will be left with a "hole" on top of it, because it is not responding to a Paint
Message that Windows sends to your program to tell it to repaint itself.
Under Windows, a better approach would be to process the Records in a Timer Event. Example:
Open Window Event Handling
Set(MyDataBase)
Timer Event Handling
Loop 10 Times Next(MyDataBase)
If ErrorCode() Break End End
Note that you prepare the Data File for processing when the Window first opens. You then
process 10 records at a time in the Timer Event. Since Timer Events have lower priority than
other Windows Events, your Program will be responsive to the User and to Events generated outside
of itself (i.e., Windows telling your Program to re-paint itself).
If you break your processing of Serial Port data into "chunks", and use the Timer
Event to process the data, you will be able to simultaneously handle 2 or more Serial Ports
at the same time, without too much degradation. It should be noted that you can't just take
the DOS version of the Loop and put it in a Windows Timer Event. Because the Accept Loop needs
to Cycle to allow other Threads to run, if it takes 10 minutes to process data in a Timer Event,
the Accept Loop will not cycle until that 10 minutes is up, and you will effectively lock out
other threads.
|