Heim  >  Artikel  >  Backend-Entwicklung  >  C# Message Queuing-Anwendung-2

C# Message Queuing-Anwendung-2

黄舟
黄舟Original
2016-12-17 16:59:101284Durchsuche

Innerhalb dieses Arrays erstellt die CWorker-Klasse eine Implementierung
der CWorkerThread-Klasse. CWorkerThread Eine Klasse (siehe unten) ist eine abstrakte Klasse, die vererbt werden muss. Die exportierte Klasse
definiert, wie Nachrichten verarbeitet werden:
aThreads = new ArrayList(); (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; Definieren Sie den Hilfstyp und fügen Sie ihn in die Hilfs-Thread-Struktur
CWorkerThread wtBase; (sfWorker.ProcessType)
{
case WorkerFormatter.SFProcessType.ProcessRoundRobin:
  wtBase = new CWorkerThreadRoundRobin(this, wfThread);
 break; WorkerFormatter.SFProcessType.ProcessAppSpecific:
  wtBase = new CWorkerThreadAppSpecific(this, wfThread);
 break; WorkerFormatter.SFProcessType.ProcessAssembly:
  wtBase = new CWorkerThreadAssembly(this, wfThread);
break; throw new Exception("Unknown Processing Type");
  }
// Einen Aufruf zum Array hinzufügen
aThreads.Insert(idx, wtBase);
}

Sobald alle Objekte erstellt wurden, können Sie sie starten, indem Sie die Start-Methode jedes Thread-Objekts aufrufen:
foreach (CWorkerThread cThread in aThreads)
cThread.Start();

Die Methoden Stop, Pause und Continue führen ähnliche Vorgänge in der foreach-Schleife aus.
Stop-Methode verfügt über die folgenden Garbage-Collection-Vorgänge:
GC.SuppressFinalize(this);

Die Stop-Methode wird im Klassendestruktor aufgerufen, sodass das Objekt korrekt beendet werden kann, ohne die Stop-Methode explizit aufzurufen
. Wenn Stop aufgerufen wird -Methode besteht keine Notwendigkeit, den
-Konstruktor zu analysieren. Die SuppressFinalize-Methode verhindert den Aufruf der Finalize-Methode des Objekts (Analyse der tatsächlichen Implementierung des

-Konstruktors).

CWorkerThread abstrakte Klasse

 CWorkerThread ist eine Klasse bestehend aus CWorkerThreadAppSpecifc, CWorkerThread
RoundRobin und Von CWorkerThreadAssembly geerbte abstrakte Klasse. Unabhängig davon, wie Sie die Nachricht verarbeiten, ist die Verarbeitung der Warteschlange zum größten Teil gleich, sodass die Klasse CWorkerThread diese Funktionalität bereitstellt.
Diese Klasse stellt abstrakte Methoden bereit (die durch tatsächliche Methoden ersetzt werden müssen), um Ressourcen zu verwalten und Nachrichten zu verarbeiten.

Die Arbeit der Klasse wird erneut durch die Methoden „Start“, „Stopp“, „Pause“ und „Fortfahren“ erledigt.

Die Eingabe- und Fehlerwarteschlangen werden in der Start-Methode referenziert. existieren Im .NET Framework werden Nachrichten vom System

Messaging-Namespace verarbeitet:

// Versuchen Sie, die Warteschlange zu öffnen und die Standard-Lese- und Schreibeigenschaften festzulegen

MessageQueue mqInput = new MessageQueue(sInputQueue);

mqInput.MessageReadPropertyFilter.Body = true;
mqInput.MessageReadPropertyFilter.AppSpecific = true; mqError = new MessageQueue(sErrorQueue);
// Wenn Sie MSMQ COM verwenden, setzen Sie den Formatierer auf ActiveX
mqInput.Formatter = new ActiveXMessageFormatter();

mqError.Formatter = new ActiveXMessageFormatter();


Sobald die Nachrichtenwarteschlangenreferenz definiert ist, wird ein Thread für die eigentliche Verarbeitungsfunktion
(genannt ProcessMessages) erstellt. Verwenden Sie im .NET Framework Der Namespace System.Threading
erleichtert die Implementierung von Threading:
procMessage = new Thread(new ThreadStart(ProcessMessages));
procMessage.Start();

 Die ProcessMessages-Funktion ist eine Verarbeitungsschleife, die auf booleschen Werten basiert. Wenn der Wert auf
False gesetzt ist, wird die Verarbeitungsschleife beendet. Daher ist der Stop des Thread-Objekts Die Methode legt nur diesen booleschen
-Wert fest, schließt dann die offene Nachrichtenwarteschlange und verbindet den Thread mit dem Hauptthread:
// Treten Sie dem Service-Thread und dem Verarbeitungsthread bei

bRun = false;

procMessage.Join();
//Schließen Sie die offene Nachrichtenwarteschlange
mqInput.Close();
mqError.Close();

Die Pause-Methode legt nur einen booleschen Wert fest, um den Verarbeitungsthread eine halbe Sekunde lang in den Ruhezustand zu versetzen:


if (bPause)
Thread.Sleep (500) ;

Schließlich ruft jede Start-, Stop-, Pause- und Continue-Methode die Zusammenfassung
OnStart, OnStop, OnPause und auf OnContinue-Methode. Diese abstrakten Methoden stellen Hooks für Klassen bereit, die
implementieren, um erforderliche Ressourcen zu erfassen und freizugeben.

Die ProcessMessages-Schleife hat die folgende Grundstruktur:

●Receive Message.

●Wenn die Nachricht erfolgreich empfangen wurde, wird die abstrakte ProcessMessage-Methode aufgerufen.

●Wenn der Empfang oder die Verarbeitung einer Nachricht fehlschlägt, senden Sie die Nachricht an die Fehlerwarteschlange.

Message mInput;
try
{
// Aus der Warteschlange lesen und 1 Sekunde warten
mInput = mqInput.Receive(new TimeSpan(0,0,0,1));
}
catch (MessageQueueException mqe)
{
// Setze die Nachricht auf null
mInput = null;
// Überprüfen Sie den Fehlercode, um festzustellen, ob eine Zeitüberschreitung aufgetreten ist
if (mqe.ErrorCode != (-1072824293) ) //0xC00E001B
{
  // Wenn es nicht zu einer Zeitüberschreitung kommt, geben Sie einen Fehler aus und protokollieren Sie die Fehlernummer
LogError("Error: " + mqe.Message);
  }
}
if (mInput != null)
{
  // Eine zu verarbeitende Nachricht abrufen und die abstrakte Methode zur Nachrichtenverarbeitung aufrufen
try
{
ProcessMessage(mInput);
}
// Fehler mit bekanntem abnormalen Status erfassen
Catch (CWorkerThreadException ex)
{
ProcessError(mInput, ex.Terminate);
  }
  // Die unbekannte Ausnahme abfangen und Terminate aufrufen
  {
 ProcessError(mInput, true);
 }
}

 Die ProcessError-Methode sendet die Fehlermeldung an die Fehlerwarteschlange. Darüber hinaus kann es auch dazu führen

Senden Sie eine Ausnahme, um den Thread zu beenden. Dies geschieht, wenn die ProcessMessage-Methode einen Beendigungsfehler oder den Typ CWorker

ThreadException auslöst.

CworkerThread exportierte Klasse

Jede Klasse, die von CWorkerThread erbt, muss OnStart, OnStop, On

Pause, OnContinue und bereitstellen ProcessMessage-Methode. Die Methoden OnStart und OnStop erfassen und geben Verarbeitungsressourcen frei. OnPause und OnContinue Methoden ermöglichen die vorübergehende Freigabe und

Wiedergewinnung dieser Ressourcen. Die ProcessMessage-Methode sollte die Nachricht verarbeiten und
auslösen, wenn ein Fehlerereignis auftritt CWorkerThreadException-Ausnahme.

Da der CWorkerThread-Konstruktor Laufzeitparameter definiert, muss die abgeleitete Klasse den Basisklassen-
-Konstruktor aufrufen:

public CWorkerThreadDerived(CWorker v_cParent, WorkerThread

Formatter v_wfThread)
: base (v_cParent, v_wfThread) {}

Die exportierte Klasse bietet zwei Arten der Verarbeitung: Senden der Nachricht an eine andere Warteschlange oder Aufrufen der Komponentenmethode
. Beide Implementierungen des Empfangens und Sendens von Nachrichten verwenden Schleifentechniken oder Anwendungsoffsets (Keeping).

in der AppSpecific-Eigenschaft der Nachricht hinterlassen) als entscheidender Faktor für die zu verwendende Warteschlange. Die Konfigurationsdatei in diesem Schema

sollte eine Liste von Warteschlangenpfaden enthalten. OnStart implementiert und Die OnStop-Methode
sollte Verweise auf diese Warteschlangen öffnen und schließen:
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 diesen Szenarien ist die Nachrichtenverarbeitung einfach: Senden Sie die Nachricht an die erforderliche Ausgabewarteschlange. Im Fall einer
-Schleife ist dieser Vorgang:

versuchen Sie

{
mqOutput[iNextQueue].Send(v_mInput);
}
catch (Ausnahme ex)
{
// Erzwungene Beendigungsausnahme bei Fehler
throw new CWorkerThreadException(ex.Message, true);
// Berechnen Sie die nächste Warteschlangennummer
iNextQueue++;
iNextQueue %= iQueues;

Die letztere Methode zum Aufrufen einer Komponente mit Nachrichtenparametern ist interessanter. Prozessnachricht Die
-Methode verwendet die IWebMessage-Schnittstelle, um eine .NET-Komponente aufzurufen. Die Methoden OnStart und OnStop
rufen die Referenz dieser Komponente ab und geben sie frei.

Die Konfigurationsdatei in diesem Szenario sollte zwei Elemente enthalten: den vollständigen Klassennamen und den
Speicherort der Datei, in der sich die Klasse befindet. Rufen Sie es gemäß der Definition in der IWebMessage-Schnittstelle für die Komponente auf Prozessmethode.

Um eine Objektreferenz zu erhalten, müssen Sie die Methode Activator.CreateInstance verwenden. diesen Brief

Die Nummer erfordert einen Montagetyp. Hier wird der Pfad und der Klassenname der Assemblydatei exportiert.
Sobald die Objektreferenz erhalten wurde, wird sie in die entsprechende Schnittstelle eingefügt:

privat IWebMessage iwmSample;

private string sFilePath, sTypeName; Assembly-Pfad und Typnamen speichern
sFilePath = wfThread.OutputName[0]; wfThread.OutputName[1];
// Einen Verweis auf das erforderliche Objekt abrufen
Assembly asmSample = Assembly.LoadFrom(sFilePath);
Type typSample = asmSample.GetType(sTypeName);
objSample = Activator.CreateInstance(typSample);
// Definieren Sie die erforderliche Schnittstelle für das Objekt
iwmSample = (IWebMessage)objSample;

Nachdem die ProcessMessage-Methode die Objektreferenz erhalten hat, ruft sie die
Process-Methode auf der IWebMessage-Schnittstelle auf:
WebMessageReturn wbrSample;
try
{
// Parameter für Methodenaufruf definieren
string sLabel = v_mInput.Label;
string sBody = (string)v_mInput.Body; iAppSpecific = v_mInput.AppSpecific;
// Rufen Sie die Methode auf und erfassen Sie den Rückgabecode
wbrSample = iwmSample.Process(sLabel, sBody, iAppSpecific);
}
catch (InvalidCastException ex)
{
// Wenn ein Fehler im Nachrichteninhalt auftritt, erzwingen Sie eine nicht terminierende Ausnahme
new CWorkerThreadException(ex.Message, false);
}
catch (Exception ex)
{
// Wenn die Assembly falsch aufgerufen wird, erzwingen Sie eine Beendigungsausnahme
werfen Sie neu CWorkerThreadException(ex.Message, true);
}
//Wenn kein Fehler vorliegt, überprüfen Sie den Rückgabestatus des Objektaufrufs
switch (wbrSample)
{
case WebMessageReturn.ReturnBad:
throw new CWorkerThreadException
   („Nachricht konnte nicht verarbeitet werden: Nachricht markiert bad", false);
case WebMessageReturn.ReturnAbort:
throw new CWorkerThreadException
   („Nachricht konnte nicht verarbeitet werden: Process terminating", true);
Standard:
break;
}

Die bereitgestellte Beispielkomponente schreibt den Nachrichtentext in eine Datenbanktabelle. Wenn ein schwerwiegender Datenbankfehler erfasst wird

Fehler, vielleicht möchten Sie den Vorgang abbrechen, aber hier markieren Sie die Nachricht einfach als Fehlermeldung
.

Da die in diesem Beispiel erstellte Klasseninstanz möglicherweise teure Datenbankressourcen anfordert und behält,

verwenden Sie die Methoden OnPause und OnContinue, um Objektverweise freizugeben und erneut abzurufen.

Erkennungsgeräte

Wie in allen guten Anwendungen werden Erkennungsgeräte verwendet, um den

Status der Anwendung zu überwachen. . NET Framework vereinfacht die Integration von Ereignisprotokollen, Leistungsindikatoren und Windows-Verwaltungsinstrumentierungsgeräten (WMI) erheblich ) in den Bewerbungsprozess einbinden. Die Messaging-Anwendung verwendet Zeitprotokolle und Leistungsindikatoren, beide aus der System.Diagnostics-Assembly.

In der ServiceBase-Klasse können Sie die Ereignisprotokollierung automatisch aktivieren. Darüber hinaus unterstützt das ServiceBase
EventLog-Mitglied das Schreiben in das Anwendungsereignisprotokoll:

EventLog.WriteEntry(sMyMessage, EventLogEntryType.Information);


Für Anwendungen, die in das Ereignisprotokoll statt in das Anwendungsprotokoll schreiben, ist es möglich, einfach
einen Verweis auf das Ereignisprotokoll zu erstellen und abzurufen Ressource ( wie in Dasselbe wie in der CWorker-Klasse gemacht),

und in der Lage sein, Protokolleinträge mit der WriteEntry-Methode zu protokollieren:

private EventLog cLog;
string sSource = ServiceControl.ServiceControlName;
string sLog = "application"// Überprüfen Sie, ob die Quelle vorhanden ist. Wenn nicht, erstellen Sie die Quelle
if (!EventLog.SourceExists(sSource))
EventLog.CreateEventSource(sSource, sLog);
// Erstellen Sie ein Protokollobjekt und verweisen Sie auf die aktuell definierte Quelle
cLog = new EventLog();
cLog.Source = sSource;// Schreiben Sie einen Eintrag in das Protokoll, um die erfolgreiche Erstellung anzuzeigen
cLog.WriteEntry("Erfolgreich erstellt", EventLogEntryType.Information);

 Das .NET Framework vereinfacht Leistungsindikatoren erheblich. Die Messaging-Anwendung stellt Zähler für jeden Verarbeitungsthread, jeden Thread-exportierten Benutzer
und die gesamte Anwendung bereit, um Nachrichten zu verfolgen.
Die Anzahl der Nachrichten und die Anzahl der pro Sekunde verarbeiteten Nachrichten. Um diese Funktionalität bereitzustellen, müssen Sie eine Klasse von Leistungsindikatoren
definieren und dann die entsprechende Zählerinstanz erhöhen.

Die Kategorie der Leistungsindikatoren wird in der OnStart-Methode des Dienstes definiert. Diese Kategorien stellen zwei Zähler dar – die Gesamtzahl der Nachrichten und die Anzahl der pro Sekunde verarbeiteten Nachrichten:
CounterCreationData[] cdMessage = new CounterCreationData[2];
cdMessage[0] = new CounterCreationData("Messages/Total", "Total
Messages Verarbeitet",

PerformanceCounterType.NumberOfItems64);

cdMessage[1] = neu CounterCreationData("Nachrichten/Sekunde",
"Eine Sekunde verarbeitete Nachrichten",
PerformanceCounterType.RateOfChangePerSecond32);
PerformanceCounterCategory.Create("MSDN Message Service", "MSDN
Message Service Counters", cdMessage);

Sobald die Leistungsindikatorkategorie definiert ist, wird ein PerformanceCounter-Objekt für den Zugriff erstellt
Fragen Sie nach der Funktion der Zählerinstanz. Ein PerformanceCounter-Objekt erfordert eine Kategorie, einen Zählernamen und einen
optionalen Instanznamen. Für den Hilfsprozess wird der Prozessname aus der XML-Datei verwendet, der Code lautet wie folgt:
pcMsgTotWorker = new PerformanceCounter("MSDN Message Service",
"Nachrichten/Gesamt", sProcessName);

pcMsgSecWorker = neu PerformanceCounter("MSDN Message Service",

"Messages/Second", sProcessName);
pcMsgTotWorker.RawValue = 0;
pcMsgSecWorker.RawValue = 0;

Um den Zähler zu erhöhen, rufen Sie einfach die entsprechende Methode auf:

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

Abschließend sollte die installierte Leistungsindikatorkategorie aus dem System gelöscht werden, wenn der Dienst beendet wird:

PerformanceCounterCategory.Delete("MSDN Message Service");

Da Leistungsindikatoren im .NET Framework funktionieren, muss ein spezieller Dienst ausgeführt werden.
Dieser Dienst (PerfCounterService) stellt gemeinsam genutzten Speicher bereit. Zählerinformationen werden in den gemeinsam genutzten
Speicher geschrieben und vom Leistungsindikatorsystem gelesen.

Installation

Bevor wir zum Schluss kommen, stellen wir kurz die Installation und das
Installationstool namens installutil.exe vor. Da diese Anwendung ist Windows-Dienst, er muss mit installutil.exe
installiert werden. Daher muss man eines von System.Configuration.Install verwenden In Assembly geerbte Installer-Klasse
:
öffentliche Klasse ServiceRegister: Installer
{
privater ServiceInstaller serviceInstaller;
privater ServiceProcessInstaller ProcessInstaller;
public ServiceRegister()
{
  // Einen Dienst-Installer erstellen
 serviceInstaller = new ServiceInstaller();
 serviceInstaller.StartType = ServiceStart.Manual;
 serviceInstaller.ServiceName = ServiceControl.ServiceControl
 Name;
 serviceInstaller.DisplayName = ServiceControl.ServiceControl
 Desc;
 Installers.Add(serviceInstaller);
  // Ein Prozessinstallationsprogramm erstellen
ProcessInstaller = new ServiceProcessInstaller();
ProcessInstaller.RunUnderSystemAccount = true;
 Installers.Add(processInstaller);
}
}

Wie in dieser Beispielklasse gezeigt, erfordern der Dienst und der Dienstprozess jeweils ein
Installationsprogramm Definieren Sie das Konto, unter dem der Dienst ausgeführt wird. Andere Installationsprogramme ermöglichen die Registrierung von Ereignisprotokollen und
Ressourcen wie Leistungsindikatoren.

Zusammenfassung

Wie aus diesem .NET Framework-Anwendungsbeispiel hervorgeht, können Anwendungen, die in der Vergangenheit nur von Visual C++
Programmierern geschrieben werden konnten, jetzt einfach objektorientiert geschrieben werden Programme durchführen. Auspuff
Obwohl unser Fokus auf C# liegt, gelten die in diesem Artikel beschriebenen Inhalte auch für Visual Basic und
Managed C++ Das Framework ermöglicht Entwicklern die Erstellung leistungsstarker, skalierbarer Windows-Anwendungen und -Dienste mit jeder Programmiersprache.

Das neue .NET-Framework vereinfacht und erweitert nicht nur die Programmiermöglichkeiten, sondern integriert auch problemlos

häufig vergessene Anwendungsinstrumentierungsgeräte (wie Leistungsüberwachungszähler und Ereignisprotokollbenachrichtigungen).
In die App integriert. Obwohl die Anwendung hier keine Windows Management Detection Devices
(WMI) verwendet, kann sie auch vom .NET Framework angewendet werden.

Das Obige ist der Inhalt der C# Message Queue Application-2. Weitere verwandte Artikel finden Sie auf der chinesischen PHP-Website (www.php.cn)!



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn