ÕªÒª£º±¾ÎĸÅÊöÒ»ÖÖÓÃÓÚ´¦ÀíÈô¸ÉÏûÏ¢¶ÓÁÐµÄ Windows ·þÎñ½â¾ö·½°¸£¬Öصã½éÉÜ .NET ¿ò¼ÜºÍ C# Ó¦ÓóÌÐò¡£
ÏÂÔØ CSharpMessageService.exe ʾÀýÎļþ (86 KB)
Ŀ¼
¼ò½é
.NET ¿ò¼ÜÓ¦ÓóÌÐò
Ó¦ÓóÌÐò½á¹¹
·þÎñÀà
¼ì²âÉ豸
°²×°
×ܽá
²Î¿¼×ÊÁÏ
¼ò½é
Microsoft ½üÆÚÍÆ³öÁËÒ»ÖÖÓÃÓÚÉú³É¼¯³ÉÓ¦ÓóÌÐòµÄÐÂÆ½Ì¨¡ª¡ªMicrosoft .NET ¿ò¼Ü¡£.NET ¿ò¼ÜÔÊÐí¿ª·¢ÈËԱʹÓÃÈκαà³ÌÓïÑÔѸËÙÉú³ÉºÍ²¿Êð Web ·þÎñºÍÓ¦ÓóÌÐò¡£Microsoft Intermediate Language (MSIL) ºÍʵʱ (JIT) ±àÒëÆ÷ʹÕâÖÖ²»ÒÀÀµÓïÑԵĿò¼ÜµÃÒÔʵÏÖ¡£
Óë .NET ¿ò¼ÜÍ¬Ê±ÃæÊÀµÄ»¹ÓÐÒ»ÖÖеıà³ÌÓïÑÔ C#£¨¶Á×÷¡°C sharp¡±£©¡£C# ÊÇÒ»ÖÖ¼òµ¥¡¢ÐÂÓ±¡¢ÃæÏò¶ÔÏóºÍÀàÐͰ²È«µÄ±à³ÌÓïÑÔ¡£ÀûÓà .NET ¿ò¼ÜºÍ C#£¨³ý Microsoft® Visual Basic® ºÍ Managed C++ Ö®Í⣩£¬Óû§¿ÉÒÔ±àд¹¦ÄÜÇ¿´óµÄ Microsoft Windows® ºÍ Web Ó¦ÓóÌÐò¼°·þÎñ¡£±¾ÎÄÌṩÁËÕâÑùµÄÒ»¸ö½â¾ö·½°¸£¬ËüµÄÖØµãÊÇ .NET ¿ò¼ÜºÍ C# ¶ø²»ÊDZà³ÌÓïÑÔ¡£C# ÓïÑԵĽéÉÜ¿ÉÒÔÔÚ¡° C# ¼ò½éºÍ¸ÅÊö£¨Ó¢ÎÄ£©¡±ÕÒµ½¡£
½üÆÚµÄÎÄÕ¡°MSMQ£º¿ÉÉìËõ¡¢¸ß¿ÉÓÃÐԵĸºÔØÆ½ºâ½â¾ö·½°¸£¨Ó¢ÎÄ£©¡±½éÉÜÁËÒ»ÖÖ½â¾ö·½°¸£¬ÓÃÓڸ߿ÉÓÃÐÔÏûÏ¢¶ÓÁÐ (MSMQ) µÄ¿ÉÉìËõ¸ºÔØÆ½ºâ½â¾ö·½°¸Ìåϵ½á¹¹¡£´Ë½â¾ö·½°¸ÖÐÉæ¼°ÁËÒ»ÖÖ½« Windows ·þÎñÓÃ×÷ÖÇÄÜÏûϢ·ÓÉÆ÷µÄ¿ª·¢·½°¸¡£ÕâÑùµÄ½â¾ö·½°¸ÒÔǰֻÓÐ Microsoft Visual C++® ³ÌÐòÔ±²ÅÄÜʵÏÖ£¬¶ø .NET ¿ò¼ÜµÄ³öÏָıäÁËÕâÖÖÇé¿ö¡£´ÓÏÂÃæµÄ½â¾ö·½°¸ÖУ¬Äú¿ÉÒÔ¿´µ½ÕâÒ»µã¡£
.NET ¿ò¼ÜÓ¦ÓóÌÐò
ÕâÀï½éÉܵĽâ¾ö·½°¸ÊÇÒ»ÖÖÓÃÀ´´¦ÀíÈô¸ÉÏûÏ¢¶ÓÁÐµÄ Windows ·þÎñ£»ÆäÖÐÿ¸ö¶ÓÁж¼ÊÇÓɶà¸öÏ߳̽øÐд¦Àí£¨½ÓÊպʹ¦ÀíÏûÏ¢£©¡£´¦Àí³ÌÐòʹÓÃÑ»··¨¼¼Êõ»òÓ¦ÓóÌÐòÌØ¶¨Öµ£¨ÏûÏ¢ AppSpecific ÊôÐÔ£©´ÓÄ¿µÄ¶ÓÁÐÁбíÖзÓÉÏûÏ¢£¬²¢Ê¹ÓÃÏûÏ¢ÊôÐÔÀ´µ÷ÓÃ×é¼þ·½·¨¡££¨Ê¾Àý½ø³ÌÒ²ÊôÓÚÕâÖÖÇé¿ö¡££©ÔÚºóÒ»ÖÖÇé¿öÏ£¬×é¼þµÄÒªÇóÊÇËüÄܹ»ÊµÏÖ¸ø¶¨µÄ½Ó¿Ú IWebMessage¡£Òª´¦Àí´íÎó£¬Ó¦ÓóÌÐòÐèÒª½«²»ÄÜ´¦ÀíµÄÏûÏ¢·¢Ë͵½´íÎó¶ÓÁÐÖС£
ÏûÏ¢Ó¦ÓóÌÐòµÄ½á¹¹ÓëÒÔǰµÄ»î¶¯Ä£°å¿â (ATL) Ó¦ÓóÌÐòÏàËÆ£¬ËüÃÇÖ®¼äµÄÖ÷Òª²»Í¬ÔÚÓÚÓÃÓÚ¹ÜÀí·þÎñµÄ´úÂëµÄ·â×°ºÍ .NET ¿ò¼Ü×é¼þµÄʹÓá£Òª´´½¨ Windows ·þÎñ£¬.NET ¿ò¼ÜÓû§½ö½öÐèÒª´´½¨Ò»¸ö´Ó ServiceBase£¨À´×Ô System.ServiceControl ³ÌÐò¼¯£©¼Ì³ÐµÄÀà¡£ÕâºÁ²»Ææ¹Ö£¬ÒòΪ .NET ¿ò¼ÜÊÇÃæÏò¶ÔÏóµÄ¡£
Ó¦ÓóÌÐò½á¹¹
Ó¦ÓóÌÐòÖÐÖ÷ÒªµÄÀàÊÇ ServiceControl£¬ËüÊÇ´Ó ServiceBase ¼Ì³ÐµÄ¡£Òò¶ø£¬Ëü±ØÐëʵÏÖ 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 ¡¢CWorkerThreadRoundRobin ºÍ CWorkerThreadAssembly ¼Ì³Ð¡£ÕâЩÀàÒÔ²»Í¬µÄ·½Ê½´¦ÀíÏûÏ¢¡£Ç°Á½¸öÀàͨ¹ý¸øÁíÒ»¶ÓÁз¢ËÍÏûÏ¢À´´¦ÀíÏûÏ¢£¨Æä²»Í¬Ö®´¦ÔÚÓÚÈ·¶¨½ÓÊÕ¶ÓÁз¾¶µÄ·½Ê½£©£¬×îºóÒ»¸öÀàÔòʹÓÃÏûÏ¢ÊôÐÔÀ´µ÷ÓÃ×é¼þ·½·¨¡£
.NET ¿ò¼ÜÄÚ²¿µÄ´íÎó´¦ÀíÊÇÒÔ»ùÀà Exception Ϊ»ù´¡µÄ¡£µ±ÏµÍ³Òý·¢»ò²¶»ñ´íÎóʱ£¬ÕâЩ´íÎó±ØÐëÊÇ´Ó Exception Öе¼³öµÄÀà¡£CWorkerThreadException Àà¾ÍÊÇÕâÑùÒ»ÖÖʵÏÖ£¬Ëüͨ¹ý¸½¼Ó¶îÍâÊôÐÔ£¨ÓÃÓÚ¶¨Òå·þÎñÊÇ·ñÓ¦¼ÌÐøÔËÐУ©À´À©Õ¹»ùÀà¡£
×îºó£¬Ó¦ÓóÌÐò°üº¬Á½Öֽṹ¡£ÕâЩֵÀàÐͶ¨ÒåÁ˸¨Öú½ø³Ì»òÏ̵߳ÄÔËÐÐʱ²ÎÊý£¬ÒÔ¼ò»¯ CWorker ºÍ CWorkerThread ¶ÔÏóµÄ½á¹¹¡£Ê¹ÓÃÖµÀàÐͽṹ£¨¶ø²»ÊÇÒýÓÃÀàÐÍÀࣩÄܹ»È·±£ÕâЩÔËÐÐʱ²ÎÊýά»¤µÄÊÇÊýÖµ£¨¶ø²»ÊÇÒýÓã©¡£
IWebMessage ½Ó¿Ú
CWorkerThread µÄʵÏÖÖ®Ò»ÊÇÒ»¸öµ÷ÓÃ×é¼þ·½·¨µÄÀà¡£Õâ¸öÃûΪ CWorkerThreadAssembly µÄÀàʹÓà IWebMessage ½Ó¿ÚÀ´¶¨Òå·þÎñºÍ×é¼þÖ®¼äµÄÔ¼¶¨¡£
Ó뵱ǰ°æ±¾µÄ Microsoft Visual Studio® ²»Í¬£¬C# ½Ó¿Ú¿ÉÒÔÔÚÈκÎÓïÑÔÖÐÏÔʽ¶¨Ò壬¶ø²»ÐèÒª´´½¨ºÍ±àÒë IDL Îļþ¡£C# IWebMessage ½Ó¿ÚµÄ¶¨ÒåÈçÏ£º
public interface IWebMessage
{
WebMessageReturn Process(string sMessageLabel, string sMessageBody, int iAppSpecific);
void Release();
}
ATL ´úÂëÖÐµÄ Process ·½·¨ÊÇΪ´¦ÀíÏûÏ¢¶øÖ¸¶¨µÄ¡£Process ·½·¨µÄ·µ»Ø´úÂ붨ÒåΪö¾ÙÀàÐÍ WebMessageReturn£º
public enum WebMessageReturn
{
ReturnGood,
ReturnBad,
ReturnAbort
}
ö¾ÙµÄ¶¨ÒåÈçÏ£ºGood ±íʾ¼ÌÐø´¦Àí£¬Bad ±íʾ½«ÏûϢдÈë´íÎó¶ÓÁУ¬Abort ±íʾÖÕÖ¹´¦Àí¡£Release ·½·¨Îª·þÎñÌṩÁËÇáËÉÇå³ýÀàʵÀýµÄ;¾¶¡£ÒòΪ½öÔÚÀ¬»ø»ØÊյĹý³ÌÖвŵ÷ÓÃÀàʵÀýµÄÎö¹¹º¯Êý£¬ËùÒÔÈ·±£ËùÓÐÕ¼Óðº¹ó×ÊÔ´£¨ÀýÈçÊý¾Ý¿âÁ¬½Ó£©µÄÀà¶¼ÓÐÒ»¸öÄܹ»ÔÚÎö¹¹Ö®Ç°±»µ÷Óõķ½·¨£¬ÓÃÀ´ÊÍ·ÅÕâЩ×ÊÔ´£¬ÕâÊÇÒ»Öַdz£ºÃµÄ¹¹Ë¼¡£
Ãû³Æ¿Õ¼ä
ÔÚÕâÀïÏȼòµ¥½éÉÜÒ»ÏÂÃû³Æ¿Õ¼ä¡£Ãû³Æ¿Õ¼äÔÊÐíÔÚÄÚ²¿ºÍÍⲿ±íʾÖн«Ó¦ÓóÌÐò×éÖ¯³ÉΪÂß¼ÔªËØ¡£·þÎñÄÚµÄËùÓдúÂë¶¼°üº¬ÔÚ MSDNMessageService.Service Ãû³Æ¿Õ¼äÄÚ¡£¾¡¹Ü·þÎñ´úÂë°üº¬ÔÚÈô¸ÉÎļþÖУ¬µ«ÊÇÓÉÓÚËüÃǰüº¬ÔÚͬһÃû³Æ¿Õ¼äÖУ¬Òò´ËÓû§²»ÐèÒªÒýÓÃÆäËûÎļþ¡£
ÓÉÓÚ IWebMessage ½Ó¿Ú°üº¬ÔÚ MSDNMessageService.Interface Ãû³Æ¿Õ¼äÖУ¬Òò´ËʹÓô˽ӿڵÄÏß³ÌÀà¾ßÓÐÒ»¸ö½Ó¿ÚÃû³Æ¿Õ¼ä¡£
·þÎñÀà
Ó¦ÓóÌÐòµÄÄ¿µÄÊǼàÊӺʹ¦ÀíÏûÏ¢¶ÓÁУ¬Ã¿Ò»¶ÓÁÐÔÚÊÕµ½ÏûϢʱ¶¼Ö´Ðв»Í¬µÄ½ø³Ì¡£Ó¦ÓóÌÐòÊÇ×÷Ϊ Windows ·þÎñÀ´ÊµÏֵġ£
ServiceBase Àà
ÈçǰËùÊö£¬·þÎñµÄ»ù±¾½á¹¹ÊÇ´Ó ServiceBase ¼Ì³ÐµÄÀà¡£ÖØÒªµÄ·½·¨°üÀ¨ OnStart¡¢OnStop¡¢OnPause ºÍ OnContinue£¬Ã¿Ò»¸öÌæ´ú·½·¨¶¼ÓëÒ»¸ö·þÎñ¿ØÖƲÙ×÷Ö±½Ó¶ÔÓ¦¡£OnStart ·½·¨µÄÄ¿µÄÊÇ´´½¨ CWorker ¶ÔÏ󣬶ø CWorker ÀàÓÖ´´½¨ CWorkerThread ¶ÔÏó£¬È»ºóÔڸöÔÏóÖд´½¨Ö´ÐзþÎñ¹¤×÷µÄÏ̡߳£
·þÎñµÄÔËÐÐʱÅäÖã¨ÒÔ¼° CWorker ºÍ CWorkerThread ¶ÔÏóµÄÊôÐÔ£©ÊÇÔÚ»ùÓÚ XML µÄÅäÖÃÎļþÖÐά»¤µÄ¡£ËüµÄÃû³ÆÓë´´½¨µÄ .exe ÎļþÏàͬ£¬µ«´øÓÐÒ»¸ö .cfg ºó׺¡£ÅäÖÃʾÀýÈçÏ£º
ProcessName="Worker1" ProcessDesc="Message Worker with 2 Threads" ProcessType="AppSpecific" ProcessThreads="2" InputQueue=".\private$\test_load1" ErrorQueue=".\private$\test_error">
ProcessName="Worker2" ProcessDesc="Assembly Worker with 1 Thread" ProcessType="Assembly" ProcessThreads="1" InputQueue=".\private$\test_load2" ErrorQueue=".\private$\test_error">
¶Ô´ËÐÅÏ¢µÄ·ÃÎÊͨ¹ýÀ´×Ô System.Configuration ³ÌÐò¼¯µÄ ConfigManager ÀàÀ´¹ÜÀí¡£¾²Ì¬ Get ·½·¨·µ»ØÐÅÏ¢µÄ¼¯ºÏ£¬ÕâЩ¼¯ºÏ½«±»Ã¶¾ÙÒÔ»ñµÃµ¥¸öÊôÐÔ¡£ÕâЩÊôÐÔ¼¯µÄÉèÖþö¶¨Á˸¨Öú¶ÔÏóµÄÔËÐÐÊ±ÌØÕ÷¡£³ýÁËÕâÒ»ÅäÖÃÎļþ£¬Äú»¹Ó¦¸Ã´´½¨¶¨Òå XML Îļþ½á¹¹µÄͼԪÎļþ£¬²¢ÔÚÆäÖÐÒýÓÃλÓÚ·þÎñÆ÷ machine.cfg ÅäÖÃÎļþÖеÄͼԪÎļþ£º
InternalName="Process" PublicName="ProcessList" PublicRowName="ProcessDefinition" SchemaGeneratorFlags="EMITXMLSCHEMA">
InternalName="Output" PublicName="OutputList" PublicRowName="OutputDefinition" SchemaGeneratorFlags="EMITXMLSCHEMA">
PrimaryTable="Process" PrimaryColumns="ProcessName" ForeignTable="Output" ForeignColumns="ProcessName" MetaFlags="USECONTAINMENT"/> ÓÉÓÚ Service Àà±ØÐëά»¤Ò»¸öÒÑ´´½¨¸¨Öú¶ÔÏóµÄÁÐ±í£¬Òò´ËʹÓÃÁË Hashtable ¼¯ºÏ£¬ÓÃÓÚ±£³ÖÀàÐͶÔÏóµÄÃû³Æ/ÊýÖµ¶ÔÁÐ±í¡£Hashtable ²»½öÖ§³Öö¾Ù£¬»¹ÔÊÐíͨ¹ý¹Ø¼ü×ÖÀ´²éѯֵ¡£ÔÚÓ¦ÓóÌÐòÖУ¬XML ½ø³ÌÃû³ÆÊÇΨһµÄ¹Ø¼ü×Ö£º 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"]; // ¼ÆËã²¢¶¨Òå½ø³ÌÀàÐÍ 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"); } // Ö´Ðиü¶àµÄ¹¤×÷ÒÔ¶ÁÈ¡Êä³öÐÅÏ¢ string sProcessName = (string)ciWorker["ProcessName"]; if (htWorkers.ContainsKey(sProcessName)) throw new ArgumentException("Process Name Must be Unique: " + sProcessName); htWorkers.Add(sProcessName, new CWorker(sfWorker)); } ÔÚÕâ¶Î´úÂëÖÐûÓаüº¬µÄÖ÷ÒªÐÅÏ¢ÊÇÊä³öÊý¾ÝµÄ»ñÈ¡¡£Ã¿Ò»¸ö½ø³Ì¶¨ÒåÖж¼ÓÐÒ»×éÏàÓ¦µÄÊä³ö¶¨ÒåÏî¡£¸ÃÐÅÏ¢ÊÇͨ¹ýÈçϵļòµ¥²éѯ¶ÁÈ¡µÄ£º 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 ºÍ Cworker Àà¶¼ÓÐÏàÓ¦µÄ·þÎñ¿ØÖÆ·½·¨£¬¸ù¾Ý·þÎñ¿ØÖƲÙ×÷½øÐе÷Óá£ÓÉÓÚ Hashtable ÖÐÒýÓÃÁËÿһ¸ö CWorker ¶ÔÏó£¬Òò´ËÐèҪö¾Ù Hashtable µÄÄÚÈÝ£¬ÒÔµ÷ÓÃÊʵ±µÄ·þÎñ¿ØÖÆ·½·¨£º foreach (CWorker cWorker in htWorkers.Values) cWorker.Start(); ÀàËÆµØ£¬ÊµÏÖµÄ OnPause¡¢OnContinue ºÍ OnStop ·½·¨ÊÇͨ¹ýµ÷Óà CWorker ¶ÔÏóÉϵÄÏàÓ¦·½·¨À´Ö´ÐвÙ×÷µÄ¡£ CWorker Àà CWorker ÀàµÄÖ÷Òª¹¦ÄÜÊÇ´´½¨ºÍ¹ÜÀí CWorkerThread ¶ÔÏó¡£Start¡¢Stop¡¢Pause ºÍ Continue ·½·¨µ÷ÓÃÏàÓ¦µÄ CWorkerThread ·½·¨¡£Êµ¼ÊµÄ CWorkerThread ¶ÔÏóÊÇÔÚStart ·½·¨Öд´½¨µÄ¡£ÓëʹÓà Hashtable ¹ÜÀí¸¨Öú¶ÔÏóÒýÓÃµÄ Service ÀàÏàËÆ£¬CWorker ʹÓà ArrayList£¨¼òµ¥µÄ¶¯Ì¬Êý×飩À´Î¬»¤Ï̶߳ÔÏóµÄÁÐ±í¡£ ÔÚÕâ¸öÊý×éÄÚ²¿£¬CWorker Àà´´½¨ÁË CWorkerThread ÀàµÄÒ»¸öʵÏÖ°æ±¾¡£CWorkerThread Àࣨ½«ÔÚÏÂÃæÌÖÂÛ£©ÊÇÒ»¸ö±ØÐë¼Ì³ÐµÄ³éÏóÀà¡£µ¼³öÀඨÒåÁËÏûÏ¢µÄ´¦Àí·½Ê½£º aThreads = new ArrayList(); for (int idx=0; 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(CWorkerThread cThread in aThreads) cThread.Start(); Stop¡¢Pause ºÍ Continue ·½·¨ÔÚ foreach Ñ»·ÀïÖ´ÐеIJÙ×÷ÀàËÆ¡£Stop ·½·¨¾ßÓÐÈçϵÄÀ¬»øÊÕ¼¯²Ù×÷£º GC.SuppressFinalize(this); ÔÚÀàÎö¹¹º¯ÊýÖн«µ÷Óà Stop ·½·¨£¬ÕâÑù£¬ÔÚûÓÐÏÔʽµ÷Óà Stop ·½·¨µÄÇé¿öÏÂÒ²¿ÉÒÔÕýÈ·µØÖÕÖ¹¶ÔÏó¡£Èç¹ûµ÷ÓÃÁË Stop ·½·¨£¬½«²»ÐèÒªÎö¹¹º¯Êý¡£SuppressFinalize ·½·¨Äܹ»·ÀÖ¹µ÷ÓöÔÏóµÄ Finalize ·½·¨£¨Îö¹¹º¯ÊýµÄʵ¼ÊʵÏÖ£©¡£ CWorkerThread ³éÏóÀà CWorkerThread ÊÇÒ»¸öÓÉ CWorkerThreadAppSpecifc¡¢CWorkerThreadRoundRobin ºÍ 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); ×îºó£¬Ã¿Ò»¸ö Start¡¢Stop¡¢Pause ºÍ 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 ·½·¨Òý·¢ÁËÖÕÖ¹´íÎó»ò CWorkerThreadException ÀàÐÍ£¬Ëü½«Ö´Ðд˲Ù×÷¡£ CworkerThread µ¼³öÀà ÈÎºÎ´Ó CWorkerThread Öм̳еÄÀà¶¼±ØÐëÌṩ OnStart¡¢OnStop¡¢OnPause¡¢OnContinue ºÍ ProcessMessage ·½·¨¡£OnStart ºÍ OnStop ·½·¨»ñÈ¡²¢ÊÍ·Å´¦Àí×ÊÔ´¡£OnPause ºÍ OnContinue ·½·¨ÔÊÐíÁÙʱÊͷźÍÖØÐ»ñÈ¡ÕâЩ×ÊÔ´¡£ProcessMessage ·½·¨Ó¦¸Ã´¦ÀíÏûÏ¢£¬²¢ÔÚ³öÏÖʧ°ÜʼþʱÒý·¢ CWorkerThreadException Òì³£¡£ ÓÉÓÚ CWorkerThread ¹¹Ô캯Êý¶¨ÒåÔËÐÐʱ²ÎÊý£¬µ¼³öÀà±ØÐëµ÷ÓûùÀ๹Ô캯Êý£º public CWorkerThreadDerived(CWorker v_cParent, WorkerThreadFormatter v_wfThread) : base (v_cParent, v_wfThread) {} µ¼³öÀàÌṩÁËÁ½ÖÖÀàÐ͵Ĵ¦Àí£º½«ÏûÏ¢·¢ËÍÖÁÁíÒ»¶ÓÁУ¬»òÕßµ÷ÓÃ×é¼þ·½·¨¡£½ÓÊպͷ¢ËÍÏûÏ¢µÄÁ½ÖÖʵÏÖʹÓÃÁËÑ»·¼¼Êõ»òÓ¦ÓóÌÐòÆ«ÒÆ£¨±£ÁôÔÚÏûÏ¢ AppSpecific ÊôÐÔÖУ©£¬×÷ΪʹÓÃÄÄÒ»¶ÓÁеľö¶¨ÒòËØ¡£´Ë·½°¸ÖеÄÅäÖÃÎļþÓ¦¸Ã°üÀ¨¶ÓÁз¾¶µÄÁÐ±í¡£ÊµÏÖµÄ OnStart ºÍ OnStop ·½·¨Ó¦¸Ã´ò¿ªºÍ¹Ø±Õ¶ÔÕâЩ¶ÓÁеÄÒýÓ㺠iQueues = wfThread.OutputName.Length; mqOutput = new MessageQueue[iQueues]; for (int idx=0; 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 { // ¶¨Òå·½·¨µ÷ÓõIJÎÊý 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); ×îºó˵Ã÷Ò»µã£¬·þÎñÖÕֹʱ£¬°²×°µÄÐÔÄܼÆÊýÆ÷Àà±ðÓ¦¸Ã´ÓϵͳÖÐɾ³ý£º PerformanceCounterCategory.Delete("MSDN Message Service"); ÓÉÓÚÐÔÄܼÆÊýÆ÷ÔÚ .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.ServiceControlName; serviceInstaller.DisplayName = ServiceControl.ServiceControlDesc; 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 ¿ò¼ÜͬÑùÒ²¿ÉÒÔÓ¦ÓÃËü¡£ ²Î¿¼×ÊÁÏ ¿ÉÉìËõµÄ¸ß¿ÉÓÃÐÔÒµÎñ¶ÔÏó½á¹¹£¨Ó¢ÎÄ£© MSMQ£º¿ÉÉìËõµÄ¸ß¿ÉÓÃÐÔ¸ºÔØÆ½ºâ½â¾ö·½°¸£¨Ó¢ÎÄ£© C# ¼ò½éºÍ¸ÅÊö£¨Ó¢ÎÄ£© C# ²Î¿¼£¨Ó¢ÎÄ£© MSDN Online .NET ÐÅÏ¢£¨Ó¢ÎÄ£© ¹ØÓÚ×÷Õß Carl Nolan ÔÚ±±¼ÓÀû¸£ÄáÑÇµÄ Microsoft µç×ÓÉÌÎñ½â¾ö·½°¸Ð¡×éµÄÎ÷Çø¹¤×÷¡£¸ÃС×éµÄ¹¤×÷ÖØµãÊÇʹÓà Microsoft Windows .NET ƽ̨¿ª·¢»ùÓÚ Internet µÄ½â¾ö·½°¸¡£ËûµÄµç×ÓÓʼþµØÖ·ÊÇ carlnol@microsoft.com¡£ -------------------------------------------------------------------------------- ÇëÒÔ IE4.0 ÒÔÉϰ汾 800 * 600 ä¯ÀÀ±¾Õ¾ ©2001 Microsoft Corporation °æÈ¨ËùÓС£±£ÁôËùÓÐȨÀû¡£

