ホームページ  >  記事  >  バックエンド開発  >  C# メッセージ キュー アプリケーション -1

C# メッセージ キュー アプリケーション -1

黄舟
黄舟オリジナル
2016-12-17 16:56:311517ブラウズ

はじめに

Microsoft は最近、統合アプリケーションを生成するための新しいプラットフォームである Microsoft
.NET Framework を立ち上げました。 。ネット このフレームワークを使用すると、開発者は任意のプログラミング言語を使用して Web
サービスとアプリケーションを迅速に生成および展開できます。 Microsoft 中間言語 (MSIL) とリアルタイム
(JIT) コンパイラーは、この言語に依存しないフレームワークを有効にします。

.NET Frameworkと同時に、新しいプログラミング言語C#(「シーシャープ」と読みます)も登場しました。
C# は、シンプルで斬新なオブジェクト指向のタイプセーフなプログラミング言語です。 .NETの活用 フレームワーク
と C# (Microsoft? Visual Basic? とマネージド C++ に加えて) を使用すると、ユーザー
は強力なコードを作成できます マイクロソフトウィンドウズ?および Web アプリケーションとサービス。この記事
では、プログラミング言語ではなく .NET Framework と C# に重点を置いたソリューションを提供します
言葉。 C# 言語の概要については、「C# の概要と概要 (英語)」を参照してください。

最近の記事「MSMQ: A Scalable, High-Availability Load Balancing Solution (English)」
高可用性メッセージ キュー (MSMQ) のスケーラブルな負荷分散のためのソリューションを紹介します
ソリューションアーキテクチャ。このソリューションには、スマート メッセージング ルーターとしての Windows サービスの開発が含まれます。このようなソリューションは、以前は Microsoft からのみ利用可能でした Visual C++ はプログラマのみが実装できますが、.NET Framework の登場によりこの状況は変わりました。これは、以下のソリューション
のケースで確認できます。

.NET Framework アプリケーション

ここで紹介するソリューションは、複数のメッセージ キューを処理するために使用される Windows サービスです。

各キューは複数のスレッドによって処理されます (メッセージの受信と処理)。ハンドラーが作る

ラウンドロビン手法またはアプリケーション固有の値 (メッセージ AppSpecific プロパティ) を使用して宛先キュー リスト
テーブルからメッセージをルーティングし、メッセージ プロパティを使用してコンポーネント メソッドを呼び出します。 (サンプルプロセスもこのカテゴリに分類されます)
状況。 ) 後者の場合、コンポーネントの要件は、指定されたインターフェイス IWeb
Message を実装することです。エラーを処理するには、アプリケーションは未処理のメッセージをエラー キューに送信する必要があります。

メッセージング アプリケーションは、以前の Active Template Library (ATL) アプリケーションと同様に構造化されています。

それらの主な違いは、サービスの管理に使用されるコードのカプセル化と

.NET Framework コンポーネントの使用です。 Windows サービスを作成するには、.NET Framework ユーザーはスレーブを作成するだけで済みます。 ServiceBase
(System.ServiceControl アセンブリから) から継承されたクラス。 .NET
フレームワークはオブジェクト指向であるため、これは驚くべきことではありません。

アプリケーションの構造

アプリケーションのメインクラスはServiceBaseから

を継承するServiceControlです。したがって、OnStart と OnStop を実装する必要があります。 メソッド、およびオプションの OnPause メソッドと

OnContinue メソッド。実際、このクラスは静的メソッド Main:

using System;

using System.ServicePROcess;


public class ServiceControl: ServiceBase

{

// サービス オブジェクトを作成するためのメイン エントリ ポイント
public static void Main()
{
ServiceBase.Run(new ServiceControl());
}

// サービスパラメータを定義するコンストラクタオブジェクト

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() {...}
}

ServiceControl クラスは一連の CWorker オブジェクトを作成します。つまり、処理する必要がある

メッセージ キューごとに作成されます。 CWorker クラスのインスタンス。定義内のキューの処理に必要なスレッドの数に応じて、CWorker クラスは一連の CWorkerThread オブジェクト。 CWorkerThread

クラスによって作成された処理スレッドが、実際のサービス作業を実行します。

CWorker クラスと CWorkerThread クラスを使用する主な目的は、サービス コントロールの Start、
Stop、Pause、Continue を確認することです。 注文。これらのプロセスはノンブロッキングである必要があるため、コマンド操作は最終的にバックグラウンド処理スレッドで実行されます。

CWorkerThreadは抽象クラスであり、CWorkerThreadAppSpecificとCWorkerThreadAppSpecificに分かれています。
CWorkerThreadRoundRobin と CWorkerThreadAssembly は継承します。これらのカテゴリは、
同じ方法でメッセージを処理します。最初の 2 つのクラスは、メッセージを別のキューに送信することでメッセージを処理します (違いは、受信キューへのパスを決定する方法にあります)。最後のクラスはメッセージ属性を使用して、

コンポーネントメソッドを使用します。


.NET Framework 内のエラー処理は、基本クラスの Exception に基づいています。システムがエラーを発生またはキャッチする場合、これらのエラーは次の原因で発生する必要があります。 例外でエクスポートされたクラス。 CWorker
ThreadException クラスは、追加のプロパティ (定義に使用される) をアタッチすることにより、そのような実装の 1 つです。
サービスを実行し続ける必要があるかどうか) を使用して基本クラスを拡張します。

最後に、アプリケーションは2つの構造で構成されます。これらの値のタイプは、ワーカー プロセスまたはスレッドの
ランタイム パラメーターを定義して、CWorker と CWorkerThread オブジェクトの構造。 (参照型クラスではなく) 値型
構造を使用すると、これらのランタイム パラメーターが (
参照ではなく) 値を維持することが保証されます。

IWebMessageインターフェース

CWorkerThreadの実装の1つは、コンポーネントのメソッドを呼び出すクラスです。
CWorkerThreadAssembly という名前のこのクラスは、 IWebMessage インターフェイスは、サービスとコンポーネント間のコントラクトを定義します。

現在のバージョンの Microsoft Visual Studio を使用していますか?これとは異なり、C# インターフェイスは、IDL ファイルを作成してコンパイルすることなく、任意の

言語で明示的に定義できます。 C# IWebMessage インターフェイスの
定義は次のとおりです:
public Interface IWebMessage
{
WebMessageReturn Process(string sMessageLabel, string sMessage
Body, int iAppSpecific);
void Release();
}

ATL コード内の Process メソッドは、メッセージを処理するために指定されます。 Process メソッドの戻りコードは、列挙型 WebMessageReturn として定義されます。


public enum WebMessageReturn

{

ReturnGood,
ReturnBad,
ReturnAbort
}

列挙の定義は次のとおりです: Good は処理を続行することを意味し、Bad はメッセージをエラーキューに書き込むことを意味し、

Abort は処理を終了することを意味します。リリース メソッドは、サービスがクラス インスタンスを簡単にクリアする方法を提供します。

クラス インスタンスのデストラクターはガベージ コレクション中にのみ呼び出されるため、
高価なリソース (データベース接続など) を消費するすべてのクラスに、破棄前に呼び出すことができるメソッドがあることを確認してください。
これらのリソースを解放することは非常に良い考えです。

名前空間

ここでは名前空間について簡単に紹介します。ネームスペースを使用すると、アプリケーションを内部表現と外部表現の両方で論理要素に編成できます。サービス内のすべてのコードは MSDNMessage に含まれています

Service.Service 名前空間。サービス コードは複数のファイルに含まれていますが、これらのファイルは同じ名前空間に含まれているため、ユーザーは他のファイルを参照する必要はありません。


IWebMessage インターフェイスは MSDNMessageService.Interface 名に含まれているため
space なので、このインターフェイスを使用するスレッド クラスにはインターフェイス名前空間があります。

サービスクラス


アプリケーションの目的は、メッセージキューを監視し、メッセージを受信したときに各キューが異なる処理を実行することです。アプリケーションは Windows サービスとして実装されます。

ServiceBaseクラス

前述したように、サービスの基本構造はServiceBaseを継承したクラスです。重要なメソッド
には、OnStart、OnStop、OnPause、および OnContinue では、各代替メソッドはサービス コントロール操作に直接対応します。 OnStart メソッドの目的は、CWorker オブジェクトを作成することです。

そして 次に、CWorker クラスは CWorkerThread オブジェクトを作成し、このオブジェクト内にサービスの作業を実行するスレッドを作成します。

サービスの実行時構成 (および CWorker オブジェクトと CWorkerThread オブジェクトのプロパティ) は、xml ベースの構成ファイルで

維持されます。作成した.exeファイルと同じ名前ですが、
.cfg 接尾辞が付きます。設定例は以下の通りです。


〈プロセスリスト〉

〈プロセス定義〉

ProcessName="Worker1"
ProcessDesc="2 つのスレッドを持つメッセージ ワーカー"
ProcessType="AppSpecific"
ProcessThreads="2"
InputQueue=".private$test_load1"
ErrorQueue=".private$test_error">



〈/OutputList〉
〈/ProcessDefinition〉
〈ProcessDefinition
ProcessName="Worker2"
ProcessDesc="1の組立作業員 スレッド"
、ProcessType="アセンブリ"
、ProcessThreads="1"
InputQueue=".private$test_load2"
ErrorQueue=".private$test_error">

OutputDefinition OutputName="C:MSDNMessageServiceMessage
Example.dll" />
OutputDefinition OutputName="MSDNMessageService.Message
Sample.ExampleClass"/>
/OutputList>


〈/構成〉

この情報へのアクセスは、System.Configuration アセンブリの Config
Manager クラスを通じて管理されます。静的 Get メソッドは、個々のプロパティを取得するために列挙される情報のコレクションを返します。これらのプロパティ セットの設定により、ヘルパー オブジェクトの実行時の特性が決まります。この
構成ファイルに加えて、定義も作成する必要があります XML ファイル構造のメタファイルであり、サーバー machine.cfg 設定ファイルにある
メタファイルを参照します:


DatabaseMeta InternalName="MessageService">
ServerWiring Interceptor="Core_XMLInterceptor"/>
InternalName="プロセス" PublicName="プロセスリスト"
PublicRowName="プロセス定義"
SchemaGeneratorFlags="EMITXMLSCHEMA">
プロパティ InternalName="プロセス名" Type="String" メタ
Flags="PRIMARYKEY" />

Value="RoundRobin" 〉


Enum InternalName="Assembly" Value="2"/>

Property InternalName="ProcessThreads" Type="Int32"
DefaultValue="1" />
プロパティ InternalName="InputQueue" Type="String" /〉
プロパティ InternalName="ErrorQueue" Type="String" /〉
プロパティ InternalName="OutputName" Type="String" />

Operator="EQUAL" />
〈/コレクション〉
〈コレクション
InternalName="出力" PublicName="OutputList"
PublicRowName="OutputDefinition"
SchemaGeneratorFlags="EMITXMLSCHEMA">
プロパティ InternalName="プロセス名" Type="String" メタ
Flags="PRIMARYKEY" />
Property InternalName="OutputName" Type="String" メタ
Flags="PRIMARYKEY" />
QueryMeta InternalName="All" MetaFlags="ALL" />
QueryMeta InternalName="QueryByFile" CellName="__FILE"
Operator="EQUAL" />

/DatabaseMeta
RelationMeta
PrimaryTable="プロセス" PrimaryColumns="プロセス名"
ForeignTable="出力"ForeignColumns="プロセス名"
MetaFlags="USECONTAINMENT"/>

Service クラスは作成された補助オブジェクトのリストを維持する必要があるため、

Hashtable コレクションを使用して型オブジェクトの名前を保持します/ 数値ペアのリスト。 Hashtable は列挙をサポートするだけでなく、キーワードによる値のクエリも可能です。アプリケーションでは、XML プロセス名
が唯一のキーワードです。
プライベートハッシュテーブル htWorkers = new Hashtable(); cWorkers = ConfigManager.Get("ProcessList", new
AppDomainSelector());
foreach (IConfigItem ciWorker in cWorkers)
{
WorkerFormatter sfWorker = new WorkerFormatter();
sfWorker.ProcessName = (文字列)ciWorker["プロセス名"]
sfWorker.ProcessDesc = (文字列)ciWorker["ProcessDesc"];
sfWorker.NumberThreads = (int)ciWorker["プロセススレッド"]
sfWorker.InputQueue = (文字列)ciWorker["InputQueue"];
sfWorker.ErrorQueue = (文字列)ciWorker["エラーキュー"];

// 计算并定义进程类型
switch ((int)ciWorker["ProcessType"])
{
case 0:
sfWorker.ProcessType = WorkerFormatter.SFProcessType.
     プロセスラウンドロビン;
休憩。
ケース1:
sfWorker.ProcessType = WorkerFormatter.SFProcessType.
ProcessAppSpecific;
休憩。
ケース 2:
sfWorker.ProcessType = WorkerFormatter.SFProcessType.
ProcessAssembly;
休憩。
デフォルト:
新しいものを投げる Exception("不明な処理タイプ");
}
// さらなる工作を读取出報
  文字列 sプロセス名 = (文字列)ciWorker["プロセス名"];
もし (htWorkers.ContainsKey(sProcessName))
throw new ArgumentException("プロセス名は一意である必要があります: "
+ sProcessName);
  htWorkers.Add(sProcessName, new CWorker(sfWorker));
}

この段階のコードに含まれていない主な情報は、データの出力の取得です。各
には、それぞれ対応する出力パラメータがあります。

string sQuery = "SELECT * FROM OutputList WHERE ProcessName=" +
  sfWorker.ProcessName + " AND Selector=appdomain://";
ConfigQuery QQuery = 新しい ConfigQuery(sQuery);
IConfigCollection cOutputs = ConfigManager.Get("OutputList",
qQuery);
int iSize = cOutputs.Count、iLoop = 0;
sfWorker.OutputName = 新しい 文字列[iSize];
foreach (cOutputs の IConfigItem ciOutput)
  sfWorker.OutputName[iLoop++] = (string)ciOutput["OutputName"];

CWorkerThread と Cworker クラスには、それぞれ対応するサービス制御メソッドがあり、サービス制御
制御操作に従って実行されます。 CWorker オブジェクトのため、適切なサービス制御方法を使用するには、
必要なハッシュテーブルの内容が必要です:
foreach (CWorker cWorker in htWorkers.Values)
cWorker.Start();

同様に、実現される OnPause、OnContinue、OnStop メソッドは、
CWorker オブジェクト上の対応するメソッドを使用して操作されます。類の主な機能Start 、

Stop、Pause および Continue メソッドは、対応する CWorkerThread メソッドを使用して制御されます。実際の

CWorkerThread オブジェクトは、Start メソッド内で作成されます。

ヘルプオブジェクト参照の Service クラスと同様に、CWorker は ArrayList (単一の動作数

グループ) を使用して、オンライン プログラム オブジェクトのリストを管理します。 (www.php.cn)!



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。