search
HomeBackend DevelopmentC#.Net TutorialC# Message Queuing Application-2

Inside this array, the CWorker class creates an implementation
of the CWorkerThread class. CWorkerThread A class (discussed below) is an abstract class that must be inherited. The exported
class defines how messages are processed:
aThreads = new ArrayList();
for (int idx=0; idx〈sfWorker.NumberThreads; idx++)
{
  WorkerThreadFormatter wfThread = new WorkerThreadFormatter();
  wfThread.PRocessName = sfWorker.ProcessName;
  wfThread.ProcessDesc = sfWorker.ProcessDesc;
  wfThread.ThreadNumber = idx;
  wfThread.InputQueue = sfWorker.InputQueue;
  wfThread.ErrorQueue = sfWorker.ErrorQueue;
  wfThread.OutputName = sfWorker.OutputName;
  // Define the auxiliary type and insert it into the auxiliary thread structure
  CWorkerThread wtBase;
  switch (sfWorker.ProcessType)
  {
  case WorkerFormatter.SFProcessType.ProcessRoundRobin:
  wtBase = new CWorkerThreadRoundRobin(this, wfThread);
   break;
  case WorkerFormatter.SFProcessType.ProcessAppSpecific:
   wtBase = new CWorkerThreadAppSpecific(this, wfThread);
   break;
  case WorkerFormatter.SFProcessType.ProcessAssembly:
  wtBase = new CWorkerThreadAssembly(this, wfThread);
  break;
 default:
   throw new Exception("Unknown Processing Type");
  }
  // Add a call to the array
  aThreads.Insert(idx, wtBase);
}

Once all objects have been created, you can start them by calling the Start method of each thread object:
foreach(CWorkerThread cThread in aThreads)
 cThread.Start();

 The Stop, Pause and Continue methods perform similar operations in the foreach loop.

Stop method has the following garbage collection operations:
GC.SuppressFinalize(this);

  The Stop method will be called in the class destructor, so that the object can be terminated correctly without explicitly calling the Stop method

. If Stop is called method, there will be no need to parse the
constructor. The SuppressFinalize method prevents calling the object's Finalize method (the actual implementation of the constructor).

CWorkerThread abstract class

 CWorkerThread is a class composed of CWorkerThreadAppSpecifc, CWorkerThread

RoundRobin and Abstract class inherited by CWorkerThreadAssembly. No matter how you handle the message, most of the processing of the queue is the same, so the CWorkerThread class provides this functionality.

This class provides abstract methods (which must be replaced by real methods) to manage resources and handle messages.

 The work of the class is once again accomplished through the Start, Stop, Pause and Continue methods.
The input and error queues are referenced in the Start method. exist In the .NET framework, messages are handled by the System.
Messaging namespace:
// Try to open the queue and set the default read and write properties

MessageQueue mqInput = new MessageQueue(sInputQueue);

mqInput.MessageReadPropertyFilter.Body = true;
mqInput.MessageReadPropertyFilter.AppSpecific = true;
MessageQueue mqError = new MessageQueue(sErrorQueue);
// If using MSMQ COM, set the formatter to ActiveX
mqInput.Formatter = new ActiveXMessageFormatter();
mqError.Formatter = new ActiveXMessageFormatter();

Once the message queue reference is defined, a thread is created for the actual processing function
(called ProcessMessages). In the .NET Framework, use System.Threading
namespace makes it easy to implement threading:
procMessage = new Thread(new ThreadStart(ProcessMessages));

procMessage.Start();


 The ProcessMessages function is a processing loop based on Boolean values. When the value is set to
False, the processing loop will terminate. Therefore, the thread object's Stop The method only sets this Boolean
value, then closes the open message queue, and joins the thread with the main thread:
// Join the service thread and processing thread

bRun = false;

procMessage.Join();
// Close the open message queue
mqInput.Close();
mqError.Close();

Pause method only sets a Boolean value to make the processing thread sleep for half a second:

if (bPause)
Thread.Sleep(500);

Finally, each Start, Stop, Pause and Continue methods will call abstract

OnStart, OnStop, OnPause and OnContinue method. These abstract methods provide hooks for classes implementing

to capture and release required resources.

 The ProcessMessages loop has the following basic structure:

●Receive Message.
● If the Message has a successful Receive, the abstract ProcessMessage method is called.
●If Receive or ProcessMessage fails, send the Message to the error queue.

Message mInput;
try
{
  // Read from the queue and wait for 1 second
  mInput = mqInput.Receive(new TimeSpan(0,0,0,1));
}
catch (MessageQueueException mqe)
{
  // Set the message to null
  mInput = null;
  // Check the error code to see if it timed out
  if (mqe.ErrorCode != (-1072824293) ) //0xC00E001B
  {
   // If it does not time out, issue an error and log the error number
  LogError("Error: " + mqe.Message);
  throw mqe;
  }
}
if (mInput != null)
{
  // Get a message to be processed and call the message processing abstract method
  try
  {
 ProcessMessage(mInput);
  }
  // Capture errors with known exception status
  catch (CWorkerThreadException ex)
  {
 ProcessError(mInput, ex.Terminate);
  }
  // Catch unknown exceptions and call Terminate
  catch
  {
  ProcessError(mInput, true);
 }
}

 The ProcessError method sends the error message to the error queue. In addition, it may also lead to
Send an exception to terminate the thread. It will do this if the ProcessMessage method throws a termination error or CWorker
ThreadException type.

CworkerThread exported class

Any class that inherits from CWorkerThread must provide OnStart, OnStop, On
Pause, OnContinue and ProcessMessage method. The OnStart and OnStop methods acquire and release processing resources. OnPause and OnContinue Methods allow temporary release and reacquisition of these resources. The ProcessMessage method should process the message and raise
when a failure event occurs CWorkerThreadException exception.

Since the CWorkerThread constructor defines runtime parameters, the derived class must call the base class

Constructor:

public CWorkerThreadDerived(CWorker v_cParent, WorkerThread
Formatter v_wfThread)
  : base (v_cParent, v_wfThread) {}

  The exported class provides two types of processing: sending the message to another queue, or calling the component method. Both implementations of receiving and sending messages use looping techniques or application offsets (keeping

Leave in the message AppSpecific property) as a deciding factor in which queue to use. The configuration file in this scenario

should include a list of queue paths. Implemented OnStart and The OnStop method
should open and close references to these queues:
iQueues = wfThread.OutputName.Length;
mqOutput = new MessageQueue[iQueues];
for (int idx=0; idx〈iQueues; idx++)
{
  mqOutput[idx] = new MessageQueue(wfThread.OutputName[idx]);
  mqOutput[idx].Formatter = new ActiveXMessageFormatter();
}

In these scenarios, message processing is simple: send the message to the necessary output queue. In the case of
loop, this process is:

try

{
  mqOutput[iNextQueue].Send(v_mInput);
}
catch (Exception ex)
{
  // Forced termination exception if error
  throw new CWorkerThreadException(ex.Message, true);
}
// Calculate the next queue number
iNextQueue++;
iNextQueue %= iQueues;

  The latter method of calling a component with message parameters is more interesting. ProcessMessage The
method uses the IWebMessage interface to call a .NET component. The OnStart and OnStop methods obtain and release the reference to this component.

 The configuration file in this solution should contain two items: the complete class name and the
location of the file where the class is located. According to the definition in the IWebMessage interface, call it on the component Process method.

  To obtain an object reference, you need to use the Activator.CreateInstance method. this letter

The number requires an assembly type. Here it is exported from the assembly file path and class name.
Once the object reference is obtained, it will be put into the appropriate interface:

private IWebMessage iwmSample;

private string sFilePath, sTypeName;
// Save assembly path and type name
sFilePath = wfThread.OutputName[0];
sTypeName = wfThread.OutputName[1];
// Get a reference to the necessary object
Assembly asmSample = Assembly.LoadFrom(sFilePath);
Type typSample = asmSample.GetType(sTypeName);
object objSample = Activator.CreateInstance(typSample);
// Define the necessary interface for the object
iwmSample = (IWebMessage)objSample;

 After obtaining the object reference, the ProcessMessage method will call the
Process method on the IWebMessage interface:
WebMessageReturn wbrSample;
try
{
  // Define the parameters of method call
  string sLabel = v_mInput.Label;
  string sBody = (string)v_mInput.Body;
  int iAppSpecific = v_mInput.AppSpecific;
  // Call the method and capture the return code
  wbrSample = iwmSample.Process(sLabel, sBody, iAppSpecific);
}
catch (InvalidCastException ex)
{
  // If an error occurs in the message content, force a non-terminating exception to be issued
  throw new CWorkerThreadException(ex.Message, false);
}
catch (Exception ex)
{
  // If the assembly is called incorrectly, force a termination exception
  throw new CWorkerThreadException(ex.Message, true);
}
// If there is no error, check the return status of the object call
switch (wbrSample)
{
  case WebMessageReturn.ReturnBad:
  throw new CWorkerThreadException
   ("Unable to process message: Message marked bad", false);
  case WebMessageReturn.ReturnAbort:
  throw new CWorkerThreadException
   ("Unable to process message: Process terminating", true);
default:
 break;
}

  The provided sample component writes the message body to a database table. If a serious database error is captured
Error, you may want to terminate the process, but here, just mark the message as an error message
.

Since the class instance created in this example may acquire and retain expensive database resources, use the OnPause and OnContinue methods to release and reacquire object references.

Detection Devices

 Like in all good applications, detection devices are used to monitor the

status of the application. . NET Framework greatly simplifies integrating event logs, performance counters, and Windows management instrumentation (WMI ) into the application process. The messaging application uses time logs and performance counters, both from the System.Diagnostics assembly.

 In the ServiceBase class, you can automatically enable event logging. Additionally, the ServiceBase
EventLog member supports writing to application event logs:

EventLog.WriteEntry(sMyMessage, EventLogEntryType.Information);


For applications that write to the event log rather than the application log, it is easy to
create and get a reference to the EventLog resource (as described in the same as done in the CWorker class),

and be able to log a log entry using the WriteEntry method:

private EventLog cLog;
string sSource = ServiceControl.ServiceControlName;
string sLog = "application";
// Check if the source exists, if not, create the source
if (!EventLog.SourceExists(sSource))
  EventLog.CreateEventSource(sSource, sLog);
// Create a log object and reference the currently defined source
cLog = new EventLog();
cLog.Source = sSource;
// Write an entry in the log to indicate successful creation
cLog.WriteEntry("Created successfully", EventLogEntryType.Information);

 The .NET framework greatly simplifies performance counters. The messaging application provides counters for each processing thread, user of thread export
and the entire application to track messages.

The number of messages and the number of messages processed per second. To provide this functionality, you need to define a class of performance counters

and then increment the corresponding counter instance.

 The category of performance counters is defined in the service OnStart method. These categories represent two counters - the total number of messages and the number of messages processed per second:
CounterCreationData[] cdMessage = new CounterCreationData[2];

cdMessage[0] = new CounterCreationData("Messages/Total", "Total

Messages Processed",
PerformanceCounterType.NumberOfItems64);
cdMessage[1] = new CounterCreationData("Messages/Second",
"Messages Processed a Second",
PerformanceCounterType.RateOfChangePerSecond32);
PerformanceCounterCategory.Create("MSDN Message Service", "MSDN
Message Service Counters", cdMessage);

Once the performance counter category is defined, a PerformanceCounter object is created to access
Ask about counter instance function. A PerformanceCounter object requires a category, counter name, and an optional instance name. For the helper process, the process name from the xml file will be used, the code is as follows:
pcMsgTotWorker = new PerformanceCounter("MSDN Message Service",

"Messages/Total", sProcessName);

pcMsgSecWorker = new PerformanceCounter("MSDN Message Service",
"Messages/Second", sProcessName);
pcMsgTotWorker.RawValue = 0;
pcMsgSecWorker.RawValue = 0;

To increment the counter value, just call the appropriate method:

pcMsgTotWorker.IncrementBy(1);
pcMsgSecWorker.IncrementBy(1);

Finally, when the service is terminated, the installed performance counter category should be deleted from the system:

PerformanceCounterCategory.Delete("MSDN Message Service");

 Because performance counters work in the .NET Framework, a special service needs to be running.
This service (PerfCounterService) provides shared memory. Counter information is written to shared
memory and read by the performance counter system.

Installation

 Before we end, let’s briefly introduce installation and the
installation tool called installutil.exe. Since this application is Windows service, it must be installed using installutil.exe
. Therefore, one needs to use one from System.Configuration.Install Installer class inherited in assembly
:
public class ServiceRegister: Installer
{
  private ServiceInstaller serviceInstaller;
  private ServiceProcessInstaller processInstaller;
  public ServiceRegister()
  {
   // Create a service installer
 serviceInstaller = new ServiceInstaller();
 serviceInstaller.StartType = ServiceStart.Manual;
  serviceInstaller.ServiceName = ServiceControl.ServiceControl
  Name;
  serviceInstaller.DisplayName = ServiceControl.ServiceControl
  Desc;
  Installers.Add(serviceInstaller);
   // Create process installer
 processInstaller = new ServiceProcessInstaller();
 processInstaller.RunUnderSystemAccount = true;
  Installers.Add(processInstaller);
  }
}

  As shown in this sample class, for a Windows service, the service and the service process each require an installer to define the account under which the service runs. Other installers allow registering event logs and
Performance counters and other resources.

Summary

 As you can see from this .NET Framework application example, applications that were previously only possible for Visual C++

programmers can now be implemented using simple object-oriented programs. exhaust
Although our focus is on C#, the content described in this article also applies to Visual Basic and
Managed C++. The new .NET The framework enables developers to create powerful, scalable Windows applications and services using any programming language.

 The new .NET Framework not only simplifies and expands programming possibilities, but also makes it easy to integrate

often forgotten application instrumentation devices (such as performance monitoring counters and event log notifications)

Incorporated into the app. Although the application here does not use Windows Management Detection Devices
(WMI), the .NET Framework can apply it as well.

The above is the content of C# Message Queue Application-2. For more related articles, please pay attention to the PHP Chinese website (www.php.cn)!


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Developing with C# .NET: A Practical Guide and ExamplesDeveloping with C# .NET: A Practical Guide and ExamplesMay 12, 2025 am 12:16 AM

C# and .NET provide powerful features and an efficient development environment. 1) C# is a modern, object-oriented programming language that combines the power of C and the simplicity of Java. 2) The .NET framework is a platform for building and running applications, supporting multiple programming languages. 3) Classes and objects in C# are the core of object-oriented programming. Classes define data and behaviors, and objects are instances of classes. 4) The garbage collection mechanism of .NET automatically manages memory to simplify the work of developers. 5) C# and .NET provide powerful file operation functions, supporting synchronous and asynchronous programming. 6) Common errors can be solved through debugger, logging and exception handling. 7) Performance optimization and best practices include using StringBuild

C# .NET: Understanding the Microsoft .NET FrameworkC# .NET: Understanding the Microsoft .NET FrameworkMay 11, 2025 am 12:17 AM

.NETFramework is a cross-language, cross-platform development platform that provides a consistent programming model and a powerful runtime environment. 1) It consists of CLR and FCL, which manages memory and threads, and FCL provides pre-built functions. 2) Examples of usage include reading files and LINQ queries. 3) Common errors involve unhandled exceptions and memory leaks, and need to be resolved using debugging tools. 4) Performance optimization can be achieved through asynchronous programming and caching, and maintaining code readability and maintainability is the key.

The Longevity of C# .NET: Reasons for its Enduring PopularityThe Longevity of C# .NET: Reasons for its Enduring PopularityMay 10, 2025 am 12:12 AM

Reasons for C#.NET to remain lasting attractive include its excellent performance, rich ecosystem, strong community support and cross-platform development capabilities. 1) Excellent performance and is suitable for enterprise-level application and game development; 2) The .NET framework provides a wide range of class libraries and tools to support a variety of development fields; 3) It has an active developer community and rich learning resources; 4) .NETCore realizes cross-platform development and expands application scenarios.

Mastering C# .NET Design Patterns: From Singleton to Dependency InjectionMastering C# .NET Design Patterns: From Singleton to Dependency InjectionMay 09, 2025 am 12:15 AM

Design patterns in C#.NET include Singleton patterns and dependency injection. 1.Singleton mode ensures that there is only one instance of the class, which is suitable for scenarios where global access points are required, but attention should be paid to thread safety and abuse issues. 2. Dependency injection improves code flexibility and testability by injecting dependencies. It is often used for constructor injection, but it is necessary to avoid excessive use to increase complexity.

C# .NET in the Modern World: Applications and IndustriesC# .NET in the Modern World: Applications and IndustriesMay 08, 2025 am 12:08 AM

C#.NET is widely used in the modern world in the fields of game development, financial services, the Internet of Things and cloud computing. 1) In game development, use C# to program through the Unity engine. 2) In the field of financial services, C#.NET is used to develop high-performance trading systems and data analysis tools. 3) In terms of IoT and cloud computing, C#.NET provides support through Azure services to develop device control logic and data processing.

C# .NET Framework vs. .NET Core/5/6: What's the Difference?C# .NET Framework vs. .NET Core/5/6: What's the Difference?May 07, 2025 am 12:06 AM

.NETFrameworkisWindows-centric,while.NETCore/5/6supportscross-platformdevelopment.1).NETFramework,since2002,isidealforWindowsapplicationsbutlimitedincross-platformcapabilities.2).NETCore,from2016,anditsevolutions(.NET5/6)offerbetterperformance,cross-

The Community of C# .NET Developers: Resources and SupportThe Community of C# .NET Developers: Resources and SupportMay 06, 2025 am 12:11 AM

The C#.NET developer community provides rich resources and support, including: 1. Microsoft's official documents, 2. Community forums such as StackOverflow and Reddit, and 3. Open source projects on GitHub. These resources help developers improve their programming skills from basic learning to advanced applications.

The C# .NET Advantage: Features, Benefits, and Use CasesThe C# .NET Advantage: Features, Benefits, and Use CasesMay 05, 2025 am 12:01 AM

The advantages of C#.NET include: 1) Language features, such as asynchronous programming simplifies development; 2) Performance and reliability, improving efficiency through JIT compilation and garbage collection mechanisms; 3) Cross-platform support, .NETCore expands application scenarios; 4) A wide range of practical applications, with outstanding performance from the Web to desktop and game development.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool