C # Message Queuing application-1

Source: Internet
Author: User
Tags msmq
Brief introduction

Microsoft recently launched a new platform for building integrated applications--microsoft
. NET Framework. The. NET Framework allows developers to quickly build and deploy the Web using any programming language
Services and applications. Microsoft Intermediate Language (MSIL) and real-time
(JIT) compiler enables this language-independent framework to be implemented.

A new programming language, C # (read "C Sharp") is also available with the. NET Framework.
C # is a simple, novel, object-oriented and type-safe programming language. Leverage the. NET Framework
and C # (in addition to Microsoft? Visual Basic? and Managed C + +), the user
Can you write a powerful Microsoft Windows? and Web applications and services. This paper
Provides a solution that focuses on the. NET framework and C # rather than the programming language
Statements were The description of the C # language can be found in "Introduction and Overview of C #".

Recent article "MSMQ: Scalable, highly available load balancing solution"
Describes a solution for scalable load balancing for high availability Message Queuing (MSMQ)
Solution architecture. This solution involves the use of a Windows service as a smart
Development scenarios for the router. Such a solution was previously available only to Microsoft Visual C + +
Programmers can, and the. NET framework has changed this situation. From the solution below
Case, you can see this.

. NET Framework Applications

The solution described here is a Windows service for handling several message queues;
Each of these queues is processed by multiple threads (receiving and processing messages). Handlers make
Use cyclic techniques or application-specific values (message AppSpecific properties) from the destination queue column
The table is routed by the message and uses the message property to invoke the component method. (the sample process also belongs to this
Case In the latter case, the requirement of the component is that it can implement the given interface iweb
Message to handle the error, the application needs to send a message that cannot be processed to the error queue.

The structure of the messaging application is similar to the previous Active Template Library (ATL) application, which
The main difference between the code used to manage the service and the. NET Framework Components
Use. To create a Windows service. NET Framework users simply need to create a ServiceBase
The class inherited from the System.servicecontrol assembly. This is no surprise, because. NET
The framework is object-oriented.

Application structure

The primary class in the application is ServiceControl, which is inherited from ServiceBase
Of Thus, it must implement the OnStart and OnStop methods, as well as the optional OnPause and
OnContinue method. In fact, a class is constructed within the static method Main:

Using System;
Using System.ServiceProcess;

public class Servicecontrol:servicebase
{
Create a main entry point for a service object
public static void Main ()
{
Servicebase.run (New ServiceControl ());
}

To define a construction object for a service parameter
Public ServiceControl ()
{
CanPauseAndContinue = true;
ServiceName = "Msdnmessageservice";
AutoLog = false;
}

protected override void OnStart (string[] args) {...}
protected override void OnStop () {...}
protected override void OnPause () {...}
protected override void OnContinue () {...}
}

The ServiceControl class creates a series of CWorker objects, that is, for each
Message Queuing creates an instance of the CWorker class. The number of threads required to process the queue by definition
The CWorker class sequentially creates a series of CWorkerThread objects. CWorkerThread
A processing thread created by the class will perform the actual service work.

The primary purpose of using the CWorker and CWorkerThread classes is to confirm that the service control Start,
Stop, Pause, and Continue commands. Because these processes must be non-blocking, the command
Will eventually be executed on the background processing thread.

CWorkerThread is an abstract class, being cworkerthreadappspecific,
Cworkerthreadroundrobin and cworkerthreadassembly inherit. These classes do not
Process messages in the same way. The first two classes process a message by sending a message to another queue, which does not
To determine the way to receive queue paths), the last class uses the message property to tune
Using component methods.

Error handling inside the. NET framework is based on the base class exception. When the system leads
Errors, these errors must be classes that are exported from exception. CWorker
The ThreadException class is an implementation that uses additional attributes (to define
Whether the service should continue to run) to extend the base class.

Finally, the application consists of two structures. These value types define the secondary process or thread's
Run-time parameters to simplify the structure of CWorker and CWorkerThread objects. Using value types
Structures, rather than reference type classes, ensure that these run-time parameters maintain a numeric value (without
is a reference).

IWebMessage interface

One of the implementations of CWorkerThread is a class that invokes a component method. This name is
The Cworkerthreadassembly class uses the IWebMessage interface to define the service and component
Agreement between the two.

With the current version of Microsoft Visual Studio? C # interfaces can be used in any
explicitly defined in the language without the need to create and compile an IDL file. of the C # IWebMessage interface
Defined as follows:
public interface IWebMessage
{
Webmessagereturn Process (String Smessagelabel, String smessage
Body, int iappspecific);
void Release ();
}

The process method in the ATL code is specified for processing the message. The return of the process method
The callback code is defined as an enumeration type Webmessagereturn:

public enum Webmessagereturn
{
Returngood,
Returnbad,
Returnabort
}

The enumeration is defined as follows: Good means to continue processing, bad means to write the message to the error queue,
Abort indicates termination processing. The Release method provides a way for the service to easily purge class instances.
Because destructors for class instances are called only during garbage collection, ensure that all
A class of expensive resources, such as a database connection, has a method that can be called before the destructor is destroyed.
This is a very good idea to release these resources.

Name space

Here is a brief introduction to namespaces. Namespaces are allowed in internal and external representations
Organize the application into logical elements. All code within the service is included in the Msdnmessage
Service.service in the name space. Although the service code is contained in several files, the
They are contained in the same namespace, so the user does not need to reference other files.

Because the IWebMessage interface is contained in the Msdnmessageservice.interface name
Space, so the thread class that uses this interface has an interface namespace.

Service class

The purpose of the application is to monitor and process message queues, and each queue receives a message
A different process. The application is implemented as a Windows service.

ServiceBase class

As mentioned earlier, the basic structure of a service is a class that inherits from ServiceBase. Important method
including OnStart, OnStop, OnPause and OnContinue, each alternative is
A service control operation directly corresponds. The purpose of the OnStart method is to create a CWorker object,
The CWorker class then creates the CWorkerThread object and then creates the execution service in the object.
The working thread.

The runtime configuration of the service (as well as the properties of the CWorker and CWorkerThread objects) is
Maintained in an XML-based configuration file. It has the same name as the. exe file you created, but
With a. cfg suffix. The configuration examples are as follows:
〈?xml version= "1.0"?
〈configuration〉
〈processlist〉
〈processdefinition
Processname= "Worker1"
Processdesc= "Message Worker with 2 Threads"
Processtype= "AppSpecific"
Processthreads= "2"
Inputqueue= ". \private$\test_load1"
Errorqueue= ". \private$\test_error"
〈outputlist〉
〈outputdefinition outputname= ". \private$\test_out11"/〉
〈outputdefinition outputname= ". \private$\test_out12"/〉
〈/outputlist〉
〈/processdefinition〉
〈processdefinition
Processname= "Worker2"
Processdesc= "Assembly Worker with 1 Thread"
Processtype= "Assembly"
processthreads= "1"
Inputqueue= ". \private$\test_load2"
Errorqueue= ". \private$\test_error"
〈outputlist〉
〈outputdefinition outputname= "C:\MSDNMessageService\Message
Example.dll "/〉
〈outputdefinition outputname= "Msdnmessageservice.message
Sample.exampleclass "/〉
〈/outputlist〉
〈/processdefinition〉
〈/processlist〉
〈/configuration〉

Access to this information is through the Config from the System.Configuration assembly
Manager class to manage. The static Get method returns a collection of information that is enumerated to
Gets a single property. The settings of these property sets determine the run-time characteristics of the helper object. Except this
Configuration file, you should also create a metafile that defines the structure of the XML file, and in which it references
Metafile located in the server machine.cfg configuration file:

〈?xml Version = "1.0"?
〈metadata xmlns= "X-schema:catmeta.xms"
〈databasemeta internalname= "Messageservice"
〈serverwiring interceptor= "Core_xmlinterceptor"/〉
〈collection
Internalname= "Process" publicname= "Processlist"
Publicrowname= "ProcessDefinition"
Schemageneratorflags= "Emitxmlschema"
〈property internalname= "ProcessName" type= "String" Meta
flags= "PRIMARYKEY"/〉
〈property internalname= "Processdesc" type= "String"/〉
〈property internalname= "Processtype" type= "Int32" Default
Value= "Roundrobin"
〈enum internalname= "Roundrobin" value= "0"/〉
〈enum internalname= "AppSpecific" value= "1"/〉
〈enum internalname= "Assembly" value= "2"/〉
〈/property〉
〈property internalname= "Processthreads" type= "Int32"
Defaultvalue= "1"/〉
〈property internalname= "Inputqueue" type= "String"/〉
〈property internalname= "Errorqueue" type= "String"/〉
〈property internalname= "Outputname" type= "String"/〉
〈querymeta internalname= "All" metaflags= "all"/〉
〈querymeta internalname= "Querybyfile" cellname= "__file"
Operator= "EQUAL"/〉
〈/collection〉
〈collection
Internalname= "Output" publicname= "outputlist"
Publicrowname= "Outputdefinition"
Schemageneratorflags= "Emitxmlschema"
〈property internalname= "ProcessName" type= "String" Meta
flags= "PRIMARYKEY"/〉
〈property internalname= "Outputname" type= "String" Meta
flags= "PRIMARYKEY"/〉
〈querymeta internalname= "All" metaflags= "all"/〉
〈querymeta internalname= "Querybyfile" cellname= "__file"
Operator= "EQUAL"/〉
〈/collection〉
〈/databasemeta〉
〈relationmeta
Primarytable= "Process" primarycolumns= "ProcessName"
Foreigntable= "Output" foreigncolumns= "ProcessName"
metaflags= "Usecontainment"/〉
〈/metadata〉

Because the service class must maintain a list of created secondary objects, a
Hashtable collection is used to persist the name/value pairs list for the type object. Hashtable does not
support enumerations only, but also allows you to query values by keyword. In the application, the XML process name
is the only keyword:
private Hashtable htworkers = new Hashtable ();
Iconfigcollection cworkers = Configmanager.get ("Processlist", New
Appdomainselector ());
foreach (Iconfigitem ciworker in cworkers)
{
Workerformatter sfworker = new Workerformatter ();
Sfworker.processname = (string) ciworker["ProcessName"];
Sfworker.processdesc = (string) ciworker["Processdesc"];
Sfworker.numberthreads = (int) ciworker["processthreads"];
Sfworker.inputqueue = (string) ciworker["Inputqueue"];
Sfworker.errorqueue = (string) ciworker["Errorqueue"];

Calculating and defining process types
switch ((int) ciworker["Processtype"])
{
Case 0:
Sfworker.processtype = Workerformatter.sfprocesstype.
Processroundrobin;
Break
Case 1:
Sfworker.processtype = Workerformatter.sfprocesstype.
processappspecific;
Break
Case 2:
Sfworker.processtype = Workerformatter.sfprocesstype.
processassembly;
Break
Default
throw new Exception ("Unknown processing Type");
}
Do more work to read the output information
String sprocessname = (string) ciworker["ProcessName"];
if (Htworkers.containskey (sprocessname))
throw new ArgumentException ("Process Name must be Unique:"
+ Sprocessname);
Htworkers.add (Sprocessname, New CWorker (Sfworker));
}

The main information that is not included in this code is the acquisition of the output data. Each process will be
There is a set of corresponding output definitions in the righteousness. This information is read by a simple query such as the following:

String squery = "SELECT * from Outputlist WHERE processname=" +
Sfworker.processname + "and selector=appdomain://";
Configquery qquery = new Configquery (squery);
Iconfigcollection coutputs = Configmanager.get ("Outputlist",
Qquery);
int isize = coutputs.count, iLoop = 0;
Sfworker.outputname = new String[isize];
foreach (Iconfigitem cioutput in coutputs)
sfworker.outputname[iloop++] = (string) cioutput["Outputname"];

CWorkerThread and CWorker classes have corresponding service control methods, depending on the service
The system operation is called. Since each of the CWorker objects is referenced in Hashtable, it is necessary to
To enumerate the contents of the Hashtable to invoke the appropriate service control method:
foreach (CWorker cworker in htworkers.values)
Cworker.start ();

Similarly, the OnPause, OnContinue, and OnStop methods are implemented by invoking the
CWorker the corresponding method on the object to perform the operation.

CWorker class

The primary function of the CWorker class is to create and manage CWorkerThread objects. Start,
The Stop, Pause, and Continue methods call the appropriate CWorkerThread method. The actual
The CWorkerThread object is created in the Start method. With the use of Hashtable management auxiliary
Similar to the service class referenced by the Help object, CWorker uses ArrayList (a simple dynamic number
Group) to maintain a list of thread objects.

The above is the C # Message Queuing application-1 of the content, more related articles please pay attention to topic.alibabacloud.com (www.php.cn)!

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.