Hume Integration has created two different .NET components for
integrating Microsoft
Windows .NET Framework applications into a distributed system using the
Distributed Message Hub (DMH) message system. The components
provide high-level methods for sending and receiving binary or text
messages,
with either send-and-reply synchronous-style interactions, or higher
performance
asynchronous-style interactions. The .NET components
feature fully CLS (Common Language Specification) compliant APIs and can
be used
from any of the Microsoft .NET programming languages, including C#, C++,
Visual Basic, and Java.
The original component, HumeDMH.dll, uses separate threads to
implement
buffered sending, and well as asynchronous receiving, and there is not a
need for the application to support an event loop, or a need to
integrate
the library code into an event loop. This component can provide
the highest level of communication performance, however, DMH messages
are delivered to the application by worker threads. The latter is
not convenient for User Interface (UI) programs because it requires
message events to be passed to the UI thread in order to update the GUI.
A newer component, DmhUiClient.dll, presents the same API but
delivers all events to the application thread that constructs the
component. For a UI application, this has the desirable simplicity
that message handling event code can directly interact with UI features
such as text displays and listboxes. Since received messages are
dispatched as events to the GUI windows event queue, there is no risk
that DMH receiving logic is blocked by a deadlock in the receiving application logic.
Message exchanges are typically directed to application servers such
as the Hume Integration Datahub, or the dmh_SQLsrv persistent database
interface. The DMH message system is remarkably easy to use with
these DMH Tcl processes because the messages are typically SQL or Tcl
text commands that are directly interpreted by the receiver.
To extend
this ease of use to the .NET client, functions are provided to parse Tcl
list text strings, or to create Tcl list text strings from string
elements. The library can also be used to exchange binary messages
which can be useful for equipment controller and device integration.
The .NET component is the software of choice for integrating new Windows applications being developed using the .NET Framework with other software processes. If you are considering the .NET Framework for new automation applications, you should be aware that the .NET software base trades performance for runtime stability and safety. It is not a real-time platform with deterministic performance, particularly in view of the automatic garbage collection. On the other hand, the IDE is among the best available, and the span of runtime library functionality is truly impressive. Its a good fit for non-realtime applications such as User Interfaces.
The POSIX C library is similar to the .NET component in that it is designed
for multi-threaded applications. The big advantage of the POSIX C
library is that the same high performance API is offered on Windows and
Unix/POSIX platforms. So if you value portability, and/or the best
performance, or need to integrate workstations into your system, the POSIX
library is indicated. The C API of the POSIX C library has the disadvantage that
memory management is manual and somewhat tedious - the user needs to call
the function dmh_free() to recover memory that is passed into the application.
The memory management disadvantages of the multi-threaded POSIX C library are overcome by using the DmhCppClient C++
library. This library features a modern C++ API that integrates
std:string and Standard Template Library (STL) classes and also
integrates automatic memory management. This library is the preferred
choice for newer C++ applications on both Windows and Linux (POSIX) platforms. Hume Integration also offers an
older single-threaded C++ library that can be used with Visual Studio 6.
The Java Package has great portability, and also supports multi-threaded applications. The Java package can provide the integration glue needed to connect web-based GUI's to an automation system. Java is also a good choice for deploying portable server logic with automatic memory management and better runtime safety. Be careful with counting on Java for more sophisticated GUI's. Our experience has been that Java GUI classes have been quirky with focus, activation, and repainting events.
The Visual Basic Active-X control is the software of choice for existing VB6 applications, and other platforms such as Delphi and LabView that are able to utilize Active-X controls. The Active-X control features transparent conversion of UTF-8 and Unicode International capable character set encodings. It also fully integrates with the IntelliSense method and parameter prompting of the IDE tools.
Don't forget Tcl/Tk - the ability to integrate with DMH messaging is built into the Tcl command set of the dmh_wish shell, so this can be your easiest and fastest deployment choice. Tcl has excellent portability, and the GUI features (Tk) are unique in being of excellent quality and portable. The Hume Datahub toolset includes popular third party extensions for object oriented programming with classes and inheritance, and also extensions for composite widgets such as tabbed notebooks.
The original .NET component is provided as the following files:
The distribution is designed and tested for current Windows Professional versions. The component is designed to successfully interoperate with recent versions of the Tcl/Tk DMH software running on any platform.
The Hume developed .NET component is a "component" as defined by the Microsoft .NET Framework. As such, it implements the System.ComponentModel.IComponent interface. Hume Integration is also using the word "component" to describe high level customizable applications such as their Data Collection Component.
The Hume .NET software uses the namespace Hume.DMH. Coding is easier if you add the statement using Hume.DMH; to the using statements of your application source code. By doing this, the namespace name, Hume.DMH, can be omitted from name references. A Visual Basic developer uses the Imports statement for the same purpose.
Your primary focus as a developer is using the class DmhClient or DmhUiClient. These classes implement the public methods to send and receive messages, and to work with the DMH message system. There are other classes in the Hume.DMH namespace but they are implemented for internal use by the Dmh[Ui]Client class.
Your design will typically use one instance of a DMH Client component per process to have a single client connection to a single DMH server. A single client connection is used for sending and receiving with multiple mailboxes simultaneously from multiple threads. More than one instance of the component per process is only needed if you wish to communicate directly with multiple DMH servers. We recommend that you not use multiple connection instances within a single process to communicate with a single DMH server.
As a developer, per the licensing terms, you are required to have the SDK DMH software installed on your development system. One reason for this requirement is to insure that you have the online documentation for the DMH system. A second major reason is so that you can run your own DMH server process to test and debug against without affecting a production system.
If you are not familiar with the DMH message system, you may want to read the mbx document which is usually installed at /usr/local/htm8X/mann/mbx.html. Your application acts a DMH message system client, and attaches to a running DMH server. Once you are connected to the DMH system, you can exchange messages with other attached processes.
To get started, you only need to know the hostname where the DMH server is running, and the DMH Groupname that has been assigned to the server. If you execute a Datahub process on your system from the command line, for example:
C:> datahub eofyou will start a DMH server running on your host, with the default DMH groupname of "mbx".
The usual application design, and the one that provides the best performance, is to connect to the DMH server during initialization, and to use this connection during the life of the application. You declare a DMH Client instance and construct it in the usual way for your chosen programming language. To simplify the discussion, our example code will only be in C#, but the other .NET languages are similar.
// declare and constuct our DMH connection instance
//DmhClient dmh = new DmhClient();
DmhUiClient dmh = new DmhUiClient();
The Init( ) method is subsequently used to connect to the server. The Init() method is overloaded - there are two versions. With one version, the DMH server's hostname and groupname are provided as arguments to the method. With the other version, Init() is called without any arguments and the server hostname and groupname are configured as the properities, RemoteHost and RemoteGroup. If the application disconnects from the server, the Init( ) method can be used again to restore the connection.
The API is organized around events, method calls, and properties. We made a choice to feature events as the preferred means of having the DMH Client instance communicate asynchronous occurrences such as the arrival of messages. There is superior IntelliSense code generation and prompting for developing event handlers than there is for coding method calls using delegates. Be sure to use the += operator to add event handler callbacks to the DMH Client instance, and take advantage of the IDE's ability to code callback methods when you press the Tab key.
An application will likely want to deploy event handlers for all of the different event types that the DmhClient class raises - see the reference section and statements in the example application. For example,
// handle tracing and diagnostic information
dmh.Trace += new TraceEventHandler(dmh_Trace);
// handle incoming asynchronous DMH messages
dmh.Whenmsg += new WhenmsgEventHander(dmh_Whenmsg);
// handle background error notifications
dmh.Error += new ErrorEventHander(dmh_Error);
Here is a summary of the kinds of errors that many of the method invocations that return a string value report. In the usual success situation, a null value is returned. When you make a method call that requires a DMH server connection, and you do not have one, the method call will return the string "No DMH server connection". If you use an improper mailbox name such as one with whitespace in it, the call will return a string such as, "mailbox name must contain only ASCII letters, digits, -, _, ., !, :, or @". These are the two main errors when initiating a method call. Most of the DMH method calls are then processed asynchronously. In other words, your method call returns, and the message communication you initiated happens in background. An error that occurs during background processing results in an Error event occurring. You do not need to write an Error event handler, but you probably should to communicate to the users of your program if an error occurs. When the Error event occurs, in most cases, the Disconnected event will also occur. You can place logic in your Disconnected event handler to initiate recovery and resume logic, exit the program, etc.
Lets discuss sending without asking for replies using the Send( ) method. This method is used to send text messages, and the BinarySend() function is used in a similar fashion to send binary messages. For example, suppose you are integrating a barcode reader. When data is read from the barcode reader device, your code is supposed to update a record in a Datahub table. You will send messages without asking for reply messages - if there is a system shutdown or communication failure, your application will know from the Disconnected event. This is more efficient than asking for a reply message at every barcode read.
// update latest read record in table barcode_reader at the Datahub
string HUB="DATAHUB";
string message =
String.Format("update barcode_reader set data_in='{0}'
where device_id='{1}'",
newdata,
myID);
dmh.Send(HUB, message);
When you send a message without waiting for a reply, it is referred to as an asynchronous send.
Often, you will want to send a message to obtain reply data. The most convenient function to use for text messages is the DoXact( ) method. The BinaryXact() function is similar and is used for binary messages. This function will take care of specifying and using a unique mailbox for your reply message, and it will take care of managing a timer in case a reply message is not forthcoming. Suppose you want to query a database table, and the DB variable is assigned the mailbox name of the dmh_SQLsrv process. The online documentation shows that the SQL standard "select" command sends multiple reply messages, but the "telect" command sends a single reply message with all of the requested data formatted as a Tcl list. The DoXact( ) function is designed for a single reply message, so your code looks like:
string reply;
string msg;
string device_id;
msg = String.Format("telect device_id from barcode_config
where display='{0}'", dmh.hostname());
reply = dmh.DoXact(DB, msg);
if (reply == "TIMEOUT")) {
// timeout or error
return -1;
}
// Parse the result- a Tcl List
// element(6) = rows of data, then (0) = first row, then (0) =
first item in row
device_id = dmh.ListElement(reply, 6, 0, 0);
// success
return 0;
Asynchronous message receiving is setup in two parts - connecting your event handling callback to the Whenmsg event, and using the Whennext() or Whenever() method calls to specify which mailbox names you are using to receive messages. Most applications will setup their receive message handlers once, and not vary it. When a message arrives, you can use the WhenmsgEventArgs structure data to determine the data of the message and which mailbox name it was sent to. The Whenmsg event sender object is the DMH Client instance. You can optionally choose to pass a reference to an application object into the receiving event handler by using the overloaded version of Whenever() that accepts a clientData argument.
// handle incoming asynchronous DMH messages
dmh.Whenmsg += new WhenmsgEventHander(dmh_Whenmsg);
dmh.Whenever("MYMAILBOX");
...
void dmh_Whenmsg(object sender,
WhenmsgEventArgs e)
{
Console.Writeline("Received:
To={0} ReplyTo={1} Text={2}},
e.destinationMailbox, e.replyMailbox, e.message);
}
By convention you should use mailbox names for receiving that end in _SQL if SQL messages are expected, _XML if XML messages are expected, and _RPC if Tcl messages are expected. There is no limit to the number of mailboxes that you use for receiving, but the design convention is that you use unique names based on the server function(s) provided. There should be only one receiving process per mailbox name in a DMH group. You may wish to create a unique mailbox name for receiving by basing the name on your hostname - see the method hostname( ).
Lets revisit the DoXact( ) function. In some situations, you may
want higher performance by sending messages and collecting the replies
asynchronously, instead of waiting for each reply before sending the next
message. You do this by setting up one or more reply mailboxes and
arming them for receiving using the Whennext( ) or Whenever( ) methods.
Instead of using DoXact( ) use the Send( ) method and specify the reply
mailbox argument. Typically a high performance application will create
a small number of unique mailbox names for replies, and re-use them.
If you are creating unique mailboxes for each reply message, use the CloseMailbox(
) function when you are done with each one, to recover resource usage.
Using System.Threading;
...
// in the logic executed by the UI thread
Thread t = new Thread(new ThreadStart(do_sequential_work);
t.Start();
...
// executed by worker thread without possibly blocking the UI
void do_sequential_work() {
String reply = dmh.DoXact("RECIPESRV_RPC", "recipe_select ...");
...
}
Be careful with the Trace event. If you turn on a lot of diagnostic tracing and are exchanging long messages, your application will be manipulating huge amounts of string data.
When declaring database tables to hold international text, base the VARCHAR( ) sizes on UTF-8 byte counts, not on the number of characters. In the most conservative case, you need to allow 3 bytes per displayed character.
Datahub table varchar fields are compatible with UTF-8 sequences representing ordinary International text. There are issues with storing UTF-8 sequences of arbitrary binary data which can be avoided or worked around:
The programming model is that you will not have more than one connection to a particular DMH server. It is typical to have only one DMH connection per application process. Communication across DMH groups can be accomplished by sending to mailbox@groupname. It is also possible to use multiple connection instances, each connected to a different DMH Group.
There should be only one reader per mailbox name in a given DMH group.
The DMH client software is able to use and resolve DMH groupname aliases as described in the online Tcl documentation. Groupname aliases are resolved at the DMH server and not at the client.
Mailbox Naming rules:
FUNCTION | DESCRIPTION |
General Comments
|
Many of the method calls return a string value which is used in the
following way to indicate success or error. The method calls return
null for the usual successful invocation, or an error message that could
be logged or displayed to the user. The most common error message
is "No DMH server connection". This message occurs when using a function
that requires a connection and Init( ) has not been called successfully,
or the DMH connection has been lost. In general, the functions do
not throw exceptions, and you do not need to use try and catch. The
ListSplit() and ListElement() methods are different in that they will throw
a FormatException if the input string cannot be parsed as a valid list.
If you use an improper mailbox name such as one with whitespace in it, the method call will return a string such as, "mailbox name must contain only ASCII letters, digits, -, _, ., !, :, or @". Most of the DMH method calls are then processed asynchronously. In other words, your method call returns, and the message communication you initiated happens during background processing. An error that occurs during background processing results in the Error event occurring. |
void Abort(DMHClient) | Any in-progress send-and-reply or modal wait transactions such as the DoXact( ) or BinaryXact() calls are aborted with return values indicating TIMEOUT. Invoking the Abort method does not affect asynchronous receiving that is setup using the Whennext( ) or Whenever( ) methods or their binary counterparts. Has no effect if not connected. |
string BinarySend(string destinationMailbox,
byte [] binaryMessage) string BinarySend(string destinationMailbox,
string BinarySend(string destinationMailbox,
string BinarySend(string destinationMailbox,
string BinarySend(string destinationMailbox,
string BinarySend(string destinationMailbox,
|
The BinarySend method is used to send binary messages.
It is similar to the Send method described below which
is intended for text messages. There are 6 overloaded varieties depending
on your desire to specify optional parameters. The optional parameter
offset
lets you specify a starting element in the byte [] array that is different
than the initial byte at offset 0. The optional parameter msglen
lets
you indicate the number of bytes in the message in the case where it is
less than the length of the byte [] array. The replyMailbox
parameter is optionally specified to indicate a reply mailbox which is
passed along with the message data to the receiver. By convention,
when a reply mailbox is indicated for a command message sent to a Datahub
mailbox or equipment interface mailbox, the command is processed, and a
reply message is sent to the reply mailbox.
Specifying the replyMailbox as null, an empty string, or as the literal text "NULL" is equivalent to not specifying a reply mailbox. Returns NULL on success, or an error message. You must be connected to use this call. |
string BinaryWhenever(string receiveMailbox)
string BinaryWhenever(string receiveMailbox, object clientData) |
Registers to receive all messages directed to the specified mailbox.
The messages are passed to the user written Binmsg event handler
as binary data. When the callback returns, the software re-arms for
receiving the next message directed to the specified mailbox. The
Disarm(
) method can be used to stop receiving.
You can optionally specify the clientData argument to be saved and passed to your event handler at the time a message arrives. A typical use would be to pass a reference to an object into your receive handler. Returns null on success, or an error message. You must be connected to use this call. |
string BinaryWhenmsg(string receiveMailbox)
string BinaryWhenmsg(string receiveMailbox, object clientData) |
Registers for receiving the next available message directed to the
specified mailbox as binary data. Calling WhenmsgAgain(
) in your Binmsg event handling code re-arms the receive registration
for the next message.
You can optionally specify the clientData argument to be saved and passed to your event handler at the time a message arrives. A typical use would be to pass a reference to an object into your receive handler. Returns null on success, or an error message. You must be connected to use this call. |
byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage)
byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, int msglen, int offset) byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, int timeoutSeconds) byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, string replyMailbox) byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, int timeoutSeconds, string replyMailbox) byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, int msglen, int offset, int timeoutSeconds) byte [] BinaryXact(string destinationMailbox, byte [] binaryMessage, int msglen, int offset, int timeoutSeconds, string replyMailbox) |
Performs a complete send and reply binary transaction with timeout
management. Optionally creates and manages a unique reply mailbox
for the send and reply transaction if the replyBox argument is not specified.
If the optional timeoutSeconds argument is not specified, the DefaultTimeout
property value is used. There are overloaded varieties to let you
specify when the binary message does not start at the beginning offset
of 0, or when it's length is less than the length of the binaryMessage
array.
The usual reply is a byte array containing the reply message. The allocated size of the byte array is the length of the message and it can be 0. In the case of TIMEOUT or other failure, the return value will be null. You can have multiple instances of BinaryXact(), DoXact( ), TimedReceive( ), or TimedBinaryReceive() active at a time but not more than one instance for a specified reply mailbox. If you specify a replyMailbox, you need to insure that the name you specify is only used by your application. It is usual to create a unique reply mailbox name, perhaps based on the hostname and process ID, assign it to a variable, and use it repeatedly. If you are not connected when using this call, the null value is returned immediately. Trace event information can be used to distinguish failure modes. |
string CloseMailbox(string mailbox) | Stops using a mailbox - disarms asynchronous receiving, aborts modal
receiving, flushes the mailbox, and removes it from existence. The
Tcl version of this call, differs because it will not flush existing messages.
Returns null on success, or an error message. You must be connected to use this call. |
int [] Counts(string mailbox) | Returns an array of three numbers, the total count of messages that
have been sent to the mailbox, the total count of messages that have been
consumed from the mailbox, and last, the current count of pending messages.
A pending message is one that exists in the queue associated with the mailbox,
and has not been consumed by reading or flushing.
You must be connected to use this call. If you are not connected, or an error occurs, the return value is null instead of the array. |
void Disarm()
void Disarm(string mailbox) |
The Disarm() method is used to end asynchronous receiving that was
initiated with the Whenever(), Whennext(), BinaryWhenever(), or BinaryWhenmsg()
methods.
If called without a boxname argument, all asynchronous receiving registrations are canceled. The Abort( ) function is similar and is used to cancel in-progress DoXact( ) and BinaryXact() calls. The call has no effect if not connected. |
void Disconnect() | The counterpart of Init( ); this method is used to disconnect from the DMH server. The SendFlush( ) function gets called to complete any in-progress sends. The Abort( ) function gets called to end any in-progress transactions. The Disarm( ) function gets called to cancel all asynchronous receiving. Has no effect if not connected. |
void Dispose() | Disconnects from the DMH Server and frees all Windows resources. Called automatically by the destructor. |
string DoXact(string destinationMailbox, string message)
string DoXact(string destinationMailbox, string message, int timeoutSeconds) string DoXact(string destinationMailbox, string message, string replyMailbox) string DoXact(string destinationMailbox, string message, int
timeoutSeconds, string replyMailbox)
|
Performs a complete send and reply text message transaction with timeout
management. Creates and manages a unique reply mailbox for the send
and reply transaction if the replyMailbox argument is not specified.
If the timeoutSeconds is not specified, or specified as 0, the DefaultTimeout
property value is used.
The usual reply is the text of the reply message. The string literal TIMEOUT is returned in case of failure. You can have multiple instances of DoXact( ) or TimedReceive( ) or their binary counterparts active at a time but not more than one instance for a specified reply mailbox. If you specify a replyMailbox, you need to insure that the name you specify is only used by your application. It is usual to create a unique reply mailbox name, perhaps based on the hostname, assign it to a variable, and use it repeatedly. If you are not connected when using this call, the TIMEOUT string is returned immediately. Trace event information can be used to show the cause. |
string Flush(string mailbox)
|
Empties a mailbox of any pending messages. A pending message
is one that has been sent to the mailbox but has not been consumed.
In other words, a pending message is waiting in a queue associated with
the mailbox name. Messages are consumed by reading or flushing.
Returns null on success, or an error message. You must be connected to use this call. |
int GroupnamePort(string groupname)
|
Used to determine the TCP/IP port number that is used by the DMH server to listen for client connections. The function is similar to the mh_name_to_socket Tcl procedure. Most applications will not have a use for this function since the server socket port is managed by the DMH software. |
string hostname()
|
Returns the TCP/IP hostname of the computer that the client software is executing on. |
string Init() string Init(string groupname, string serverHostname)
|
Performs the initial connection to the DMH message server. The connection
will be setup or an error result will be obtained before returning.
If called with no arguments, the property values RemoteGroup and RemoteHost are used. The server hostname can be specified as a TCP/IP hostname, or as an IP address string. Init errors include
When the initialization is successfully completed, the Connected event occurs. If Init fails, depending on how the Init call fails, the Error event may occur. If the connection to the DMH server is ever lost, the Disconnected event occurs. |
StringBuilder ListAppend(string list, string element);
StringBuilder ListAppend(StringBuilder list, string element1); StringBuilder ListAppend(StringBuilder list, string element1, string element2); StringBuilder ListAppend(StringBuilder list, string element1, string element2, element3); StringBuilder ListAppend(StringBuilder list, string element1,
string element2, element3, element4);
|
These methods are used to add one to four list elements to text that is formatted as a Tcl list. It is a good programming practice to use ListAppend or ListJoin to build a Tcl list, in order to make sure that imbedded white space or other special characters are properly delimited with curly braces or escaped with backslashes. A null value may be passed as any of the string argument values, in order to represent an empty list or empty element. However, a null value should not be passed as a System.Text.StringBuilder argument. The System.Text.StringBuilder class is designed to support more efficient string modification than using instances of the string class. The input StringBuilder objects are modified by reference and returned as the return value of the methods. You can construct a StringBuilder instance that does not contain any characters to represent an empty list. The overloaded method calls make it convenient to add up to four list elements in one call. If you need to add more elements, call the methods repeatedly. |
string ListElement(string list, int index1);
string ListElement(string list, int index1, int index2); string ListElement(string list, int index1, int index2, int index3); |
This function is similar to the lindex function of Tcl. It will parse text formatted as a Tcl list and return the specified element. Arguments index2 and index3 may be used to indicate that parsing of the TclList should continue up to two additional levels as a nested list structure. If a specified index is out of bounds, an empty string is returned. Not all strings are valid Tcl lists. If an invalid list is parsed, the method call throws the FormatException. |
string ListJoin(string [] argv); | Joins together strings as Tcl list elements forming a result string that is a Tcl list. Braces are added as needed to delimit empty elements, or to delimit special Tcl character sequences involving backslashes , square brackets, etc. |
string [] ListSplit(string list) | ListSplit( ) parses a string formatted as a Tcl list into an array of string elements. The function understands the Tcl usage of quotes, braces and backslash sequences. Not all strings are valid Tcl lists. If an invalid list is parsed, the method call throws the FormatException. Failure occurs when there are unmatched braces, unmatched quotes, or non-whitespace following braces or quotes. |
string Product() | The idea here is that if this API is implemented for another product, a different string should be returned in case the using software needs to know the difference. The Hume DMH software returns a two element list with "DMH" as the first element, and a Copyright message as the second element. |
string [] ReceiveList() | Returns a string array of the mailboxes you are listening for messages on. Does not show mailbox names that have in-progress event callbacks. This command is useful for debugging, and it is not used in a typical application. The result is an empty array when you are not connected. |
string Send(string destinationMailbox, string message);
string Send(string destinationMailbox, string message, string
replyMailbox);
|
Send a message to a mailbox, optionally with a reply mailbox indicated.
By convention, when a reply mailbox is indicated for a command message
sent to a Datahub mailbox or equipment interface mailbox, the command is
processed, and a reply message is sent to the reply mailbox.
Specifying the reply mailbox as null, an empty string, or as the literal text "NULL" is equivalent to not specifying a reply mailbox. Sending to the mailbox name "TRACE" sends the message to the DMH Server Trace Facility. The dmh_send function corresponds to the Tcl mbx put and mbx putr commands. See the BinarySend() method to send binary data. Returns null on success, or an error message. You must be connected to use this call. |
void SendFlush() | When you send messages, the calls return immediately and the messages are queued for sending. Since TCP/IP is relatively fast, the messages are transferred into the network layer fairly quickly. If you want to block until all of the pending send data is written to the network layer, call this method. |
string ServerStatus()
|
Returns a string value formatted as a Tcl list containing the information
presented in the Tcl DMH status window. The information can be parsed
by the application to determine status information on every mailbox that
is currently in use. This command is useful for debugging, and is
not used for ordinary application logic.
The first element of the list is a list of 5 elements:
Subsequent elements in the list are lists of four or five elements:
Additional elements may exist in the list
if there are DMH clients that are not currently waiting to receive messages.
These elements are formatted as:
You must be connected to use this call. |
string TimedReceive(string receiveMailbox, int timeoutSeconds); | Waits for a message to be received in the specified mailbox. If the call succeeds, the return value is the message data. If the call fails, the return value is the literal string "TIMEOUT". If you are not connected, the call fails immediately with the return value "TIMEOUT". Trace event information can be used to show the TIMEOUT cause. If the TimeoutSeconds argument is passed as 0, the DefaultTimeout value is used. |
byte [] TimedBinaryReceive(string receiveMailbox, int timeoutSeconds); | Waits for a binary message to be received in the specified mailbox. If the call succeeds, the return value is the message data. If the call fails, the return value is null. If you are not connected, the call fails immediately with the return value of null. Trace event information can be used to show the failure cause. If the TimeoutSeconds argument is passed as 0, the DefaultTimeout value is used. |
string Version() | Returns a string value formatted as a two element Tcl list consisting of the DMH protocol version, and the library component configuration management Id string. Current software returns the "1.1" to as the first element to indicate compatibility with DMH protocol version 1.1. |
string Whenever(string receiveMailbox) | Registers to receive all messages directed to the specified mailbox.
When a message is received, a Whenmsg event occurs. When the
event handling callback returns, the software re-arms for receiving the
next message directed to the specified mailbox. The Disarm( ) function
can be used to stop receiving.
You can optionally specify the clientData argument to be saved and passed to your event handler at the time a message arrives. A typical use would be to pass a reference to an object. Returns null on success, or an error message. You must be connected to use this call. |
string Whennext(string receiveMailbox); | Register for receiving the next available message directed to the specified
mailbox. When a message is received, a Whenmsg event occurs.
Calling WhenmsgAgain( ) in the event handling code re-arms the receive
registration for the next message.
You can optionally specify the clientData argument to be saved and passed to your callback at the time a message arrives. A typical use would be to pass a reference to an object. Note - this method would have been named Whenmsg() to preserve the correspondence with other DMH software, except that the Whenmsg name is being used as the event type name. Returns null on success, or an error message. You must be connected to use this call. |
string WhenmsgAgain() | The Whennext( ) function functions as a one-shot. In other
words,
receiving is stopped after receiving one message. Calling the
WhenmsgAgain()
function from the receive handler re-registers to receive the next
message. This method is available for the DmhClient class where
the app handling logic is executed by the DMH receiving thread and the
Whennext context is known. The method is not supported by the
DmhUiClient since messages are passed off to the UI thread and the
Whenmsg context is lost. Returns null on success, or an error message. You must be connected to use this call. |
The Hume .NET client software is licensed for development and runtime use at no additional charge for computers that are licensed for development use of the Hume Integration Datahub SDK. We ask that developers install the Tcl executables and actively use the Tcl executables for testing and development, instead of developing against production servers. Also, we ask that developers install the Tcl online documentation and use it to supplement the material presented in this document.
Hume Integration is also pleased to offer separate runtime licenses for using the .NET Client software on systems that are not licensed as development systems. In other words, runtime usage of the .NET Client software is licensed separately from the Datahub SDK runtime license.