首頁 後端開發 C#.Net教程 C#訊息佇列應用程式 -2

C#訊息佇列應用程式 -2

Dec 17, 2016 pm 04:59 PM

在這個陣列內部,CWorker 類別建立了 CWorkerThread類別的實作版
本。 CWorkerThread 類別(將在下面討論)是一個必須繼承的抽象類別。導出
類別定義了訊息的處理方式:
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;
  // 定義輔助類型,並將其插入輔助執行緒結構
  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");
  }
  // 新增對陣列的呼叫
  aThreads.Insert(idx, wtBase);
}

  一旦所有的物件都已創建,就可以透過呼叫每個執行緒物件的 Start方
法來啟動它們:
foreach(CWorkerThreadeach cThread in aThreads)
  cThread.Start();

  Stop、Pause 和 Continue 方法在 foreach循環裡執行的操作類似。
Stop方法有如下的垃圾收集操作:
GC.SuppressFinalize(this);

  在類別析構函數中將呼叫 Stop 方法,這樣,在沒有明確呼叫 Stop 方
法的情況下也可以正確地終止物件。如果呼叫了 Stop 方法,將不需要析
構函數。 SuppressFinalize方法能夠防止呼叫物件的 Finalize 方法(析 

構函數的實際實作)。

CWorkerThread 抽象類別

  CWorkerThread 是 CWorkerThreadAppSpecifc、CWorkerThread
RoundRobin 和 CWorkerThreadAssembly繼承的抽象類別。無論如何處理消
息,隊列的大部分處理是相同的,所以 CWorkerThread類別提供了這項功能。
這個類別提供了抽象方法(必須被實際方法取代)以管理資源和處理訊息。

  類別的工作再一次透過 Start、Stop、Pause 和 Continue 方法來實現。
在 Start方法中引用了輸入和錯誤佇列。在 .NET 框架中,訊息由 System.
Messaging 名稱空間處理:
// 嘗試開啟佇列,並設定預設的讀寫屬性
MessageQueue mqInput = new MessageQueue(sInputQueue);
mqInput.MessageReadPropertyFilter.Body = true;
mqInput.MessageReadPropertyFilter.AppSpecific = true;
MessageQueue mqError = new MessageQueue(sErrorQueue);
// 如果使用 MSMQ COM,則將格式化程式設為 ActiveX
mqInput.Formatter = new ActiveXMessageFormatter();
mqError.Formatter = new ActiveXMessageFormatter();

  一旦定義了訊息佇列引用,即會建立一個執行緒用於實際的處理函數
(稱為 ProcessMessages)。在 .NET 框架中,使用 System.Threading
名稱空間很容易實作執行緒處理:
procMessage = new Thread(new ThreadStart(ProcessMessages));
procMessage.Start();

  ProcessMessages 函數是基於 Boolean值的處理循環。當數值設為
False,處理循環將終止。因此,線程物件的 Stop 方法只設定這一Boolean
值,然後關閉開啟的訊息佇列,並加入帶有主執行緒的執行緒:
// 加入服務執行緒
bRun = false;
procMessage.Join();
// 關閉開啟的訊息佇列
mqInput.Close();
mqError.Close();

Pause 方法只設定一個Boolean 值,讓處理執行緒休眠半秒鐘:

if (bPause)
  Thread.Sleep(500);

『個、Pa和Continue 方法將呼叫抽象的
OnStart 、OnStop、OnPause 和 OnContinue 方法。這些抽象方法為實作
的類別提供了掛鉤,以捕獲和釋放所需的資源。

  ProcessMessages 循環具有以下基本結構:
●接收Message。
●如果Message具有成功的Receive,則呼叫抽象ProcessMessage方法。
●如果Receive或ProcessMessage失敗,將Message傳送至錯誤佇列。

Message mInput;
try
{
  // 從佇列中讀取,並等待 1 秒
  mInput = mqInput.Receive(new TimeSpan(0,0,0,1));
}
catch (MessageQueueException mqe)
{
  // 將訊息設為 null
  mInput = null;
  // 查看錯誤代碼,了解是否逾時
  if (mqe.ErrorCode != (-1072824293) ) //0xC00E001B
  {
   // 若未逾時,發出錯誤並記錄錯誤編號
   LogError("Error: " + mqe.Message);
   throw mqe;
  }
}
if (mInput != null)
{
  // 得到一個要處理的訊息,呼叫處理訊息抽象方法
  try
  {
   ProcessMessage(mInput);
  }
  // 捕捉已知異常狀態的錯誤
  catch (CWorkerThreadException ex)
  {
   ProcessError(mInput, ex.Terminate);
  }
  // 捕捉未知異常,並呼叫 Terminate
  catch
  {
   ProcessError(mInput, true);
  }
}

  ProcessError方法將錯誤的訊息傳送至錯誤佇列。另外,它也可能引
發異常來終止執行緒。如果ProcessMessage方法引發了終止錯誤或 CWorker
ThreadException類型,它將執行此操作。

CworkerThread 導出類別

  任何從 CWorkerThread繼承的類別都必須提供 OnStart、OnStop、On
Pause、OnContinue和 ProcessMessage 方法。 OnStart 和 OnStop方法獲
取並釋放處理資源。 OnPause 和 OnContinue 方法允許暫時釋放和重新獲
取這些資源。 ProcessMessage方法應該處理訊息,並在出現失敗事件時引
發 CWorkerThreadException 異常。

  由於 CWorkerThread建構子定義執行階段參數,因此導出類別必須呼叫基底類別
建構子:
public CWorkerThreadDerived(CWorker v_cParent, WorkerThread
Formatter v_wfThread)
  : base (v_cParent, v_wfThread) {}

  導出類別提供了兩種類型的處理:將訊息傳送至另一個佇列,或呼叫群組
件方法。接收和發送訊息的兩種實現使用了循環技術或應用程式偏移(保
留在訊息 AppSpecific屬性中),作為使用哪一個佇列的決定因素。此方案
中的設定檔應該包括佇列路徑的清單。實現的 OnStart和 OnStop 方法
應該開啟和關閉這些佇列的參考:
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();

在這些方案中,訊息的處理很簡單:將訊息傳送必要的輸出佇列。在
循環情況下,這個過程為:
try
{
  mqOutput[iNextQueue].Send(v_mInput);
}
catch (Exception ex)
{
  // 如果錯誤強制終止異常
  throw new CWorkerThreadException(ex.Message, true);
}
// 計算下一個佇列號碼
iNextQueue++;
iNextQueue %= iQueues;

  後一種呼叫帶有訊息參數的元件的實作方法比較有趣。 ProcessMessage
方法使用 IWebMessage介面調入一個 .NET 元件。 OnStart 和 OnStop 方
法取得並釋放此組件的引用。

  此方案中的設定檔應該包含兩個項目:完整的類別名稱和類別所在檔案的
位置。依照 IWebMessage介面中的定義,在元件上調用 Process方法。

  要取得物件引用,需要使用 Activator.CreateInstance 方法。此函
數需要一個程序集類型。在這裡,它是從程序集檔案路徑和類別名稱中導出的。
一旦取得物件引用,它將被放入適當的介面:
private IWebMessage iwmSample;
private string sFilePath, sTypeName;
// 儲存組件路徑與型別名稱
sFilePath = wfThread.OutputName[0];
sTypeName = wfThread.OutputName[1];
// 取得必要物件的參考
Assembly asmSample = Assembly.LoadFrom(sFilePath);
Type typSample = asmSample.GetType(sTypeName);
object objSample = Activator.CreateInstance(typSample);
// 定義給物件的必要介面
iwmSample = (IWebMessage)objSample;

  取得物件參考後,ProcessMessage方法會在 IWebMessage介面上呼叫
Process 方法:
WebMessageReturn wbrSample;
try
{
  // 定義方法呼叫的參數
  string sLabel = v_mInput.Label;
  string sBody = (string)v_mInput.Body;
  int iAppSpecific = v_mInput.AppSpecific;
  // 呼叫方法並捕捉回傳程式碼
  wbrSample = iwmSample.Process(sLabel, sBody, iAppSpecific);
}
catch (InvalidCastException ex)
{
  // 如果在訊息內容中發生錯誤,則強制發出一個非終止異常
  throw new CWorkerThreadException(ex.Message, false);
}
catch (Exception ex)
{
  // 如果錯誤呼叫組件,則強制發出終止異常
  throw new CWorkerThreadException(ex.Message, true);
}
// 如果沒有錯誤,則檢查物件呼叫的回傳狀態
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;
}

  提供的範例元件將訊息正文寫入資料庫表。如果擷取到嚴重資料庫錯位
誤,您可能想要終止處理過程,但是在這裡,僅將訊息標記為錯誤的消
息。

  由於此範例中建立的類別實例可能會取得並保留昂貴的資料庫資源,所
以用 OnPause和 OnContinue 方法釋放和重新取得物件參考。

檢測設備

  就像在所有優秀的應用程式中一樣,檢測設備用於監測應用程式的狀
態。 。 NET 框架大大簡化了將事件日誌、效能計數器和 Windows管理偵測
裝置(WMI )納入應用程式的過程。訊息應用程式使用時間日誌和效能計
數器,二者都是來自 System.Diagnostics 組件。

  在 ServiceBase類別中,您可以自動啟用事件日誌。另外,ServiceBase
EventLog成員支援寫入應用程式事件日誌:
EventLog.WriteEntry(sMyMessage, EventLogEntryType.Information);

  對於寫入事件日誌而不是應用程式日誌的應用程序,它能夠很容易地
創建和獲取 EventLog 資源的引用(正如在 CWorker類別中所做的一樣),
並且能夠使用 WriteEntry 方法記錄日誌項目:
private EventLog cLog;
string sSource = ServiceControl.ServiceControlName;
string sLog = "application";
// 查看來源是否存在,如果不存在,則建立來源
if (!EventLog.SourceExists(sSource))
  EventLog.CreateEventSource(sSource, sLog);
// 建立日誌對象,並引用現在定義的來源
cLog = new EventLog();
cLog.Source = sSource;
// 在日誌中寫入條目,表示建立成功
cLog.WriteEntry("已成功建立", EventLogEntryType.Information);

  .NET 框架大幅簡化了效能計數器。對於每一個處理線程、線程導出
的用戶和整個應用程序,這一消息應用程式都能提供計數器,用於跟踪消
息數量和每秒鐘處理訊息的數量。若要提供此功能,您需要定義效能計數器
的類別,然後增加對應的計數器實例。

  效能計數器的類別在服務 OnStart方法中定義。這些類別代表兩種計
數器-訊息總數和每秒鐘處理的訊息數:
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);

  一旦定義了效能計數器類別,將建立 PerformanceCounter 物件以訪
問計數器實例功能。 PerformanceCounter物件需要類別、計數器名稱和一
個可選的實例名稱。對於輔助進程,將使用來自 xml檔案的進程名稱,代
碼如下:
pcMsgTotWorker = new PerformanceCounter("MSDN Message Service",
"Messages/Total", sProcessName);
pcMsgSecWorker = new PerformanceCounter("MSDN Message Service",
"Messages/Second", sProcessName);
pcMsgTotWorker.RawValue = 0;
pcMsgSecWorker.RawValue = 0;

要增加計數器的值,只需要呼叫適當的方法:

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

最後說明一點,服務終止時,安裝的效能計數器類別應該從系統中刪除:

PerformanceCounterCatef.

  由於效能計數器在.NET 框架中工作,因此需要運行一項特殊的服務。
此服務(PerfCounterService)提供了共享記憶體。計數器資訊將寫入共享
內存,並被性能計數器系統讀取。

安裝

  在結束以前,我們來簡要介紹一下安裝以及稱為 installutil.exe的
安裝工具。由於此應用程式是 Windows服務,它必須使用installutil.exe
來安裝。因此,需要使用一個從 System.Configuration.Install 組件
中繼承的 Installer類別:
public class ServiceRegister: Installer
{
  private ServiceInstaller serviceInstaller;
  private ServiceProcessInstaller processInstaller;
  public ServiceRegister()
  {
   // 創建服務安裝程序
   serviceInstaller = new ServiceInstaller();
   serviceInstaller.StartType = ServiceStart.Manual;
   serviceInstaller.ServiceName = ServiceControl.ServiceControl
   Name;
   serviceInstaller.DisplayName = ServiceControl.ServiceControl
   Desc;
   Installers.Add(serviceInstaller);
   // 建立進程安裝程序
   processInstaller = new ServiceProcessInstaller();
   processInstaller.RunUnderSystemAccount = true;
   Installers.Add(processInstaller);
  }
}

  如此示例類別所示,對於一個 Windows服務,服務和服務進程各需要一
個安裝程序,以定義運行服務的帳戶。其他安裝程式允許註冊事件日誌和
性能計數器等資源。

總結

  從這個 .NET 框架應用程式範例中可以看出,以前只有 Visual C++
程式設計師能夠編寫的應用程序,現在使用簡單的物件導向程式即可實現。盡
管我們的重點是 C# ,但本文所述的內容也同樣適用於 Visual Basic 和
Managed C++.新的 .NET 框架使開發人員能夠使用任何程式語言來創建功
能強大、可伸縮的 Windows應用程式和服務。

  新的 .NET 框架不僅簡化和擴展了編程的種種可能,還能夠輕鬆地將
人們經常遺忘的應用程式檢測設備(例如性能監測計數器和事件日誌通知)
合併到應用程式中。儘管這裡的應用程式沒有使用 Windows管理檢測設備
(WMI ),但 .NET 框架同樣也可以應用它。 

 以上就是C#訊息佇列應用程式 -2的內容,更多相關文章請關注PHP中文網(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1250
24
使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

xml怎麼改格式 xml怎麼改格式 Apr 03, 2025 am 08:42 AM

可以採用多種方法修改 XML 格式:使用文本編輯器(如 Notepad )進行手工編輯;使用在線或桌面 XML 格式化工具(如 XMLbeautifier)進行自動格式化;使用 XML 轉換工具(如 XSLT)定義轉換規則;或者使用編程語言(如 Python)進行解析和操作。修改時需謹慎,並備份原始文件。

See all articles