C#.NET Winform使用线程承载WCF (硬编码配置)
winform同步承载WCF时,遇到大量请求,可能会阻塞UI线程。这时就需要开个线程来承载WCF。
1.硬编码形式创建WCF服务,WCFServer类:
using CommonUtils; using System; using System.Net; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Web; using System.Threading; namespace WcfYeah { public class WCFServer { public WebServiceHost host = null; ////// 线程承载时sleep时间 /// const int SleepTime = 100; private Thread _thread; /// /// WCF是否在运行 /// private bool _isRunning; /// /// win server 2008以下用同步承载,以上用线程承载 /// bool _useThreadHost = true; public WCFServer() { /* 硬编码形式配置WCF服务 * WebServiceHost需要在项目中右键引用System.ServiceModel.Web.dll程序集 * */ //对外连接数,根据实际情况加大 if (ServicePointManager.DefaultConnectionLimit < 100) System.Net.ServicePointManager.DefaultConnectionLimit = 100; string port = "16110"; Uri baseURI = new Uri("http://localhost:" + port.ToString() + "/myapi"); //注意:这里是实现类,不是接口,否则会报:ServiceHost 仅支持类服务类型。 host = new WebServiceHost(typeof(Service1), baseURI); WebHttpBinding binding = new WebHttpBinding(); // 这里不需要安全验证 binding.Security.Mode = WebHttpSecurityMode.None; host.AddServiceEndpoint(typeof(IService1), binding, ""); binding.MaxReceivedMessageSize = 2147483647; binding.MaxBufferSize = 2147483647; binding.MaxBufferPoolSize = 2147483647; binding.OpenTimeout = new TimeSpan(0, 10, 0); binding.CloseTimeout = new TimeSpan(0, 10, 0); binding.SendTimeout = new TimeSpan(0, 10, 0); binding.ReceiveTimeout = new TimeSpan(0, 10, 0); //项目需要引用System.Runtime.Serialization.dll binding.ReaderQuotas.MaxDepth = 2147483647; binding.ReaderQuotas.MaxStringContentLength = 2147483647; binding.ReaderQuotas.MaxArrayLength = 2147483647; binding.ReaderQuotas.MaxBytesPerRead = 2147483647; binding.ReaderQuotas.MaxNameTableCharCount = 2147483647; ServiceThrottlingBehavior mdBehavior = new ServiceThrottlingBehavior() { MaxConcurrentCalls = 160, MaxConcurrentInstances = 260, MaxConcurrentSessions = 100 }; host.Description.Behaviors.Add(mdBehavior); #region 注册和初始化变量 //注册 _thread = new Thread(RunService); Version v2008 = new Version("6.0.0.0"); Version osver = System.Environment.OSVersion.Version; GLog.WLog("当前系统版本是:" + osver.ToString()); if (osver.CompareTo(v2008) >= 0) { _useThreadHost = true; GLog.WLog("系统是2008或以上"); } else { _useThreadHost = false; GLog.WLog("系统是2008以下"); } #endregion } public void Start() { if (_useThreadHost) { GLog.WLog("Start() 线程承载,_isRunning:" + _isRunning); if (!_isRunning) { GLog.WLog("Start() _thread.Start()"); _thread.Start(); } } else { #region 同步承载 GLog.WLog("Start() 同步承载 "); try { host.Open(); } catch (Exception ex) { GLog.WLog("服务启动失败:" + ex.Message); throw ex; } #endregion } } public void Close() { GLog.WLog("wcfservice Close"); if (_useThreadHost) { GLog.WLog("wcfservice Close 线程上停止WCF"); lock (this) { _isRunning = false; } } else { #region 同步 GLog.WLog("wcfservice Close 同步停止WCF"); try { if (host != null) { host.Close(); } host = null; } catch (Exception ex) { GLog.WLog("wcfservice Close host.Close();时异常:" + ex.Message); } #endregion } } /// /// 线程承载WCF /// void RunService() { try { _isRunning = true; host.Open(); GLog.WLog("RunService host.Open();"); while (_isRunning) { Thread.Sleep(SleepTime); } host.Close(); GLog.WLog("RunService host.Close();"); ((IDisposable)host).Dispose(); GLog.WLog("RunService host Dispose;"); } catch (Exception ex) { GLog.WLog("RunService 异常;" + ex.Message); try { if (host != null) host.Close(); } catch (Exception exClose) { GLog.WLog("host.Close();异常" + exClose.Message); } } } } }
GLog类:
using System; using System.IO; namespace CommonUtils { public static class GLog { static object _lockObj = new object(); public static void WLog(string content) { lock (_lockObj) { string curPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName); string logDir = "Logs"; string logDirFullName = Path.Combine(curPath, logDir); try { if (!Directory.Exists(logDirFullName)) Directory.CreateDirectory(logDirFullName); } catch { return; } string fileName = "Logs" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"; string logFullName = Path.Combine(logDirFullName, fileName); try { using (FileStream fs = new FileStream(logFullName, FileMode.Append, FileAccess.Write)) using (StreamWriter sw = new StreamWriter(fs)) sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " " + content); } catch { return; } } } } }
IService1:
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:
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 = "输入实体为空:" + DateTime.Now.ToString(); else myret.StringValue = "输入实体不为空:" + DateTime.Now.ToString(); } catch (Exception ex) { myret.StringValue = "发生异常:" + ex.Message; } return myret; } } }
2.管理员权限启动这个WINFORM程序:
using System; using System.Windows.Forms; using WcfYeah; namespace WindowsForms承载WCF { public partial class Form1 : Form { WCFServer wcfs = null; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { wcfs = new WCFServer(); wcfs.Start(); lblTip.Text = "服务已运行"; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { try { if (wcfs != null) { wcfs.Close(); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }