runliuv

runliuv@cnblogs

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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;

        /// <summary>
        /// 线程承载时sleep时间
        /// </summary>
        const int SleepTime = 100;

        private Thread _thread;

        /// <summary>
        /// WCF是否在运行
        /// </summary>
        private bool _isRunning;

        /// <summary>
        /// win server 2008以下用同步承载,以上用线程承载
        /// </summary>
        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
            }
        }

        /// <summary>
        /// 线程承载WCF
        /// </summary>
        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);
            }
        }
    }
}

-

posted on 2021-11-30 10:40  runliuv  阅读(290)  评论(0编辑  收藏  举报