C#.NET Windows服務承載WCF
Windows服務的製作、安裝可以參考這篇:
C#.NET 操作Windows服務(安裝、卸載) – runliuv – 部落格園 (cnblogs.com)
本篇會在這個解決方案基礎上,繼續修改。
一、製作WCF
我們在原有解決方案上添加一個「WCF 服務庫」,為名「WcfYeah」。
在WcfYeah中額外引用System.ServiceModel.Web.dll程式集。
修改IService1.cs:
using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; namespace WcfYeah { // 注意: 使用「重構」菜單上的「重命名」命令,可以同時更改程式碼和配置文件中的介面名「IService1」。 [ServiceContract] public interface IService1 { [OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] CompositeType geta(CompositeType composite); } // 使用下面示例中說明的數據約定將複合類型添加到服務操作。 // 可以將 XSD 文件添加到項目中。在生成項目後,可以通過命名空間「WcfYeah.ContractType」直接使用其中定義的數據類型。 [DataContract] public class CompositeType { bool boolValue = true; string stringValue = "Hello "; [DataMember] public bool BoolValue { get { return boolValue; } set { boolValue = value; } } [DataMember] public string StringValue { get { return stringValue; } set { stringValue = value; } } } }
修改Service1.cs:
using System; using System.ServiceModel; namespace WcfYeah { // 調整 ServiceBehavior,使其支援並發 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)] public class Service1 : IService1 { public CompositeType geta(CompositeType composite) { CompositeType myret = new CompositeType(); try { if(composite==null) myret.StringValue = "[0]輸入實體為空:" + DateTime.Now.ToString(); else myret.StringValue = "[1]輸入實體不為空:" + DateTime.Now.ToString(); } catch (Exception ex) { myret.StringValue = "發生異常:" + ex.Message; } return myret; } } }
增加一個WCFServer.cs:
using System.Net; using System.ServiceModel.Web; using System.Threading; namespace WcfYeah { public class WCFServer { public WebServiceHost host = null; public WCFServer() { #region 優化調整 //對外連接數,根據實際情況加大 if (ServicePointManager.DefaultConnectionLimit < 100) System.Net.ServicePointManager.DefaultConnectionLimit = 100; int workerThreads;//工作執行緒數 int completePortsThreads; //非同步I/O 執行緒數 ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads); int blogCnt = 100; if (workerThreads < blogCnt) { // MinThreads 值不要超過 (max_thread /2 ),否則會不生效。要不然就同時加大max_thread ThreadPool.SetMinThreads(blogCnt, blogCnt); } #endregion //注意:這裡是實現類,不是介面,否則會報:ServiceHost 僅支援類服務類型。 host = new WebServiceHost( typeof(WcfYeah.Service1)); } public void Start() { host.Open(); } public void Close() { if (host != null) { host.Close(); } } } }
二、在Windows服務中調用WCF
在windows服務庫中引用WcfYeah這個項目,再引用System.ServiceModel.dll 和System.ServiceModel.Web.dll程式集。
修改windows服務的OnStart和OnStop方法,完整內容如下:
using CommonUtils; using System; using System.ServiceModel; using System.ServiceProcess; using WcfYeah; namespace ADemoWinSvc { public partial class Service1 : ServiceBase { WCFServer aw = null; public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { try { if (aw == null) { aw = new WCFServer(); } if (aw.host.State == CommunicationState.Opening || aw.host.State == CommunicationState.Opened) { GLog.WLog("[1]服務已啟動。"); return; } aw.Start(); GLog.WLog("[2]服務已啟動"); } catch (Exception ex) { GLog.WLog("OnStart ex:" + ex.Message); } } protected override void OnStop() { try { aw.Close(); GLog.WLog("服務已停止"); } catch (Exception ex) { GLog.WLog("OnStop ex:" + ex.Message); } } } }
在windows服務庫中添加一個應用配置文件(App.config),用來配置WCF服務,內容如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="WcfYeah.Service1" behaviorConfiguration="behaviorThrottled"> <host> <baseAddresses> <add baseAddress = "//localhost:16110/myapi/" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- 除非完全限定,否則地址相對於上面提供的基址--> <endpoint address="" binding="webHttpBinding" contract="WcfYeah.IService1" bindingConfiguration="WebHttpBinding_IService"> </endpoint> </service> </services> <bindings> <webHttpBinding> <binding name="WebHttpBinding_IService" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/> </binding> </webHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="behaviorThrottled"> <serviceThrottling maxConcurrentCalls="96" maxConcurrentSessions="600" maxConcurrentInstances="696" /> <!-- 為避免泄漏元數據資訊, 請在部署前將以下值設置為 false --> <serviceMetadata httpGetEnabled="False" httpsGetEnabled="False"/> <!-- 要接收故障異常詳細資訊以進行調試, 請將以下值設置為 true。在部署前設置為 false 以避免泄漏異常資訊 --> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
編譯ADemoWinSvc項目,將編譯好的ADemoWinSvc.exe、ADemoWinSvc.exe.config和WcfYeah.dll這3個文件複製到WINFORM程式編譯輸出目錄,與Windows服務操作.exe文件放在一起。
用管理員許可權啟動Windows服務操作.exe,點擊安裝按鈕。
進入Logs文件夾,查看Logs文件,如果顯示「[2]服務已啟動」,說明windows服務安裝成功,WCF正常啟動。
使用POSTMAN調用。
地址://localhost:16110/myapi/geta
方法:POST
請求報文: