zoukankan      html  css  js  c++  java
  • 使用WCF的一些问题

     一个扫描出库程序,采用单实例、单线程模型,主要防止同个号多台电脑同时扫描出库(因为支持手动批量出库)

    View Code
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.ComponentModel;
      6 using System.ServiceModel;
      7 using System.Threading;
      8 using DotNetHalfGoodsHouse.EFModel;
      9 using System.Data.SqlClient;
     10 namespace DotNetHalfGoodsHouse.Services
     11 {
     12     #region 接口定义
     13     [ServiceContract]
     14     public interface IOutScanService
     15     {
     16         [OperationContract]
     17         OutScanResponse PostScan(OutScanRequest request);
     18         [OperationContract]
     19         string GetMaxOrderId();
     20 
     21     }
     22     #endregion
     23 
     24     #region 服务实现
     25     [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
     26     public class OutScanService : IOutScanService, IDisposable
     27     {
     28 
     29 
     30         public OutScanResponse PostScan(OutScanRequest request)
     31         {
     32           
     33             Console.WriteLine(string.Format("PN:{0},被调用了!:ThreadId:{1}", request.PN, Thread.CurrentThread.ManagedThreadId));
     34 
     35             var response = new OutScanResponse() 
     36             { 
     37                Code=2,
     38                ErrMsg="错误",
     39                Amount=0
     40             };
     41 
     42             try
     43             {
     44                 #region 扫描出库
     45                 using (JL_MFGEntities dbx = new JL_MFGEntities(ModelSetting.ModelConnString))
     46                 {
     47                     var rmBreakEnt = dbx.RMBreak.FirstOrDefault(ent => ent.PFIFOID == request.PN);
     48 
     49                     //记录是否存在
     50                     if (rmBreakEnt == null) throw new ScanException("该PN不存在!", 401);
     51 
     52                     //PN相关信息
     53                     response.Batno = rmBreakEnt.batno.ToString().Trim();
     54                     response.CarType = rmBreakEnt.p_yw.Trim();
     55                     response.Output = rmBreakEnt.Poutput.Value;
     56                     response.PlanId = rmBreakEnt.PlanID;
     57                     response.MPartNo = rmBreakEnt.partno.Trim();
     58                     response.MPartName = rmBreakEnt.p_partnoName.Trim();
     59                     response.Amount = rmBreakEnt.partnototalqty.Value;
     60 
     61                     //检测状态
     62                     if (rmBreakEnt.IsOut.Trim() != "") throw new ScanException("已发状态为'是',该记录已经被扫描出库!", 402);
     63                     //检测发料记录
     64                     var findItem = dbx.ExecuteStoreQuery<int?>("Select count(*) from storage_fixbin Where fifoid=@PN", new SqlParameter("@PN", request.PN)).FirstOrDefault();
     65                      if (findItem.HasValue && findItem.Value > 0) throw new ScanException("已存在发料记录,该记录已经被其他用户扫描",403);
     66 
     67                     //更改发料状态
     68                     rmBreakEnt.IsOut = "";
     69                     rmBreakEnt.OutDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
     70                     rmBreakEnt.OutOperator = request.Username;
     71 
     72                     //添加发料记录
     73                     var fixbin = new Storage_Fixbin()
     74                     {
     75                         #region
     76                         PlanID = rmBreakEnt.PlanID,
     77                         FGpartno = rmBreakEnt.FGpartno,
     78                         p_yw = rmBreakEnt.p_yw,
     79                         p_FGName = rmBreakEnt.p_FGName,
     80                         Batno = rmBreakEnt.batno,
     81                         Poutput = rmBreakEnt.Poutput,
     82                         FIFOID = rmBreakEnt.PFIFOID,
     83                         Barcode = request.EmpCard,
     84                         partno = rmBreakEnt.partno,
     85                         partname = rmBreakEnt.p_partnoName,
     86                         supplier = rmBreakEnt.p_supplier,
     87                         unit = rmBreakEnt.UM,
     88                         OutticketID = request.OrderId,//出库单号
     89                         OutSubID = request.OrderItemId,//子单号
     90                         OutQty = rmBreakEnt.partnototalqty,
     91                         OutDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
     92                         OutOperator = request.Username,
     93                         Shift = request.EmpGroup,
     94                         ShiftMonitor = request.EmpName,
     95                         TicketStatus = "生产性领料",
     96                         Ptype = "发料",
     97                         Machine = request.Machine,
     98                         Reason = "正常发送"
     99                         #endregion
    100 
    101                     };
    102                     dbx.Storage_Fixbin.AddObject(fixbin);
    103                     //更新预定量
    104                     var rmReserveEnt = dbx.RMHoldQty.FirstOrDefault(ent => ent.partno == fixbin.partno);
    105                     if (rmReserveEnt != null)
    106                     {
    107 
    108                         rmReserveEnt.holdqty -= rmBreakEnt.partnototalqty.Value;
    109                     }
    110 
    111                     #region 处理端子预定量
    112                     if (rmBreakEnt.Stock.Trim() == "端子")
    113                     {
    114                         var rmHandTEnt = dbx.HandTerminal.FirstOrDefault(ent => ent.partno == rmBreakEnt.partno && ent.Barcode == request.EmpCard);
    115                         if (rmHandTEnt == null) //执行添加
    116                         {
    117                             rmHandTEnt = new HandTerminal()
    118                             {
    119                                 Barcode = request.EmpCard,
    120                                 Name = request.EmpName,
    121                                 Machine = request.Machine,
    122                                 partno = rmBreakEnt.partno,
    123                                 partname = rmBreakEnt.p_partnoName,
    124                                 p_brand = rmBreakEnt.p_brand,
    125                                 supplier = rmBreakEnt.p_supplier,
    126                                 unit = rmBreakEnt.UM,
    127                                 InQty = rmBreakEnt.partnototalqty,
    128                                 Updatedate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")
    129 
    130 
    131                             };
    132                             dbx.HandTerminal.AddObject(rmHandTEnt);
    133                         }
    134                         else //执行更新
    135                         {
    136                             if (!rmHandTEnt.InQty.HasValue) rmHandTEnt.InQty = 0;
    137                             rmHandTEnt.InQty += rmBreakEnt.partnototalqty;
    138 
    139                         }
    140                     }
    141 
    142                     #endregion
    143 
    144                     dbx.SaveChanges();
    145 
    146                 }
    147                 #endregion
    148                 response.Msg = "成功";
    149                 response.ErrMsg = "";
    150                 response.Code = 1;
    151             }
    152             catch (ScanException ex)
    153             {
    154 
    155 
    156                 response.ErrMsg = ex.Message;
    157                 response.Code = ex.Code;
    158             }
    159             catch (Exception ex)
    160             {
    161                 response.Code = 400;
    162 
    163                 response.ErrMsg = ex.Message;
    164                 if (ex.InnerException != null)
    165                     response.ErrMsg += string.Format("\r\n========Inner Exception=========\r\n{0}", ex.InnerException.Message);
    166             }
    167 
    168 
    169             return response;
    170         }
    171 
    172         
    173         public void Dispose()
    174         {
    175             
    176         }
    177 
    178 
    179         public string GetMaxOrderId()
    180         {
    181             using (JL_MFGEntities dbx = new JL_MFGEntities(ModelSetting.ModelConnString))
    182             {
    183                 var list = dbx.ExecuteStoreQuery<string>("Select Max(OutTicketiD) from Storage_Fixbin").ToList();
    184                 if (list.Count > 0)
    185                 {
    186                     var orderId = list[0].Trim();
    187                     var newId=long.Parse(orderId) +1;
    188                     orderId="0000000000" + newId;
    189                     return orderId.Substring(orderId.Length - 10, 10);
    190 
    191                 }
    192 
    193             }
    194             return "0000000001";
    195         }
    196     }
    197     #endregion
    198 
    199     #region 请求结构
    200 
    201     public class OutScanRequest
    202     {
    203         public string EmpName { get; set; }
    204         public string EmpCard { get; set; }
    205         public string EmpGroup { get; set; }
    206         public string Username { get; set; }
    207         public string PN { get; set; }
    208         public string Machine { get; set; }
    209         public string OrderId { get; set; }
    210         public int OrderItemId { get; set; }
    211     }
    212     public class OutScanResponse
    213     {
    214         /// <summary>
    215         /// 1成功,2失败
    216         /// </summary>
    217         public int Code { get; set; }
    218         public string ErrMsg { get; set; }
    219         public string Msg { get; set; }
    220         public string PlanId { get; set; }
    221         public string CarType { get; set; }
    222         public decimal Output { get; set; }
    223         public string Batno { get; set; }
    224         public string MPartNo { get; set; }
    225         public string MPartName { get; set; }
    226         public decimal Amount { get; set; }
    227     }
    228     [Serializable]
    229     public class ScanException : Exception
    230     {
    231         public int Code { get; set; }
    232         public ScanException(string msg,int code)
    233             : base(msg)
    234         {
    235             this.Code = code;
    236         }
    237     }
    238     #endregion
    239 }

    WCF采用TCP方式,并且多个请求使用同个TCP连接(在完成调用请求后使用proxy.close()关闭TCP链接)

    View Code
            private IOutScanService _proxy;
            private IOutScanService ScanService
            {
                get
                {
                    if (_proxy == null)
                    {
                        TryOpenChannel();
    
                    }
                    else
                    {
                        var cObj = _proxy as ICommunicationObject;
                        if (cObj.State == CommunicationState.Faulted
                            || cObj.State == CommunicationState.Closed
                            || cObj.State == CommunicationState.Closing
    
                            )
                        {
                            TryOpenChannel();
                        }
                    }
                    return _proxy;
                }
    
            }
            private void TryOpenChannel()
            {
                try
                {
                    _proxy = WCFHelper.Factory.CreateChannel();
                    (_proxy as ICommunicationObject).Open();
                }
                catch (Exception)
                {
                    _proxy = null;
                    throw;
                }
            }

    在局域网使用不对绑定使用加密,需要注意的是该配置要在Server端与Client端同时设置。

    View Code
        #region WCF帮助类
       
        public class WCFHelper
        {
    
            private static ChannelFactory<IOutScanService> _channelFac;
    
            public static ChannelFactory<IOutScanService>  Factory
            {
                get
                {
                    if (_channelFac == null)
                    {
                        _channelFac =
                            new ChannelFactory<IOutScanService>(new NetTcpBinding(SecurityMode.None),
                            EndpointStr);
    
                    }
                    return _channelFac;
                }
            }
    
            private static string EndpointStr
            {
                get
                {
                    return DotNetHalfGoodsHouse.EFModel.ModelSetting.GetSetting("ServiceEndpoint",
                        "net.tcp://192.168.1.31:8888/OutScanService");
                }
            }
        }

     采用匿名异步委托调用,防止界面卡死

    View Code
            private void txtPN_KeyDown(object sender, KeyEventArgs e)
            
            {
                if (e.KeyCode == Keys.Enter)
                {
                    try
                    {
                        SetEnabled(false);
    
                        Post();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    finally
                    {
                        SetEnabled(true);
                        txtPN.Text = "";
                        txtPN.Focus();
                    }
                }
            }
            #endregion
            private void SetEnabled(bool v)
            {
                if (v)
                {
    
                    this.Cursor = Cursors.Arrow;
    
                }
                else
                {
                    this.Cursor = Cursors.WaitCursor;
    
                }
                dgvScnList.Cursor = this.Cursor;
    
                txtPN.Enabled = v;
                btnOut.Enabled = v;
                cbxMaterialType.Enabled = v;
                cbxIncharge.Enabled = v;
                cbxEmpGroup.Enabled = v;
            }
    
    
            
    
    
            private OutScanRequest PreRequest(string pn)
            {
                var request = new OutScanRequest();
    
    
                if (string.IsNullOrWhiteSpace(pn)) throw new DataInputException("请输入PN码!");
                if (!pn.StartsWith("P"))
                {
                    pn = "0000000000" + pn;
                    pn = "P" + pn.Substring(pn.Length - 9);
                }
                request.PN = pn;
                request.EmpCard = txtEmpCard.Text.Trim();
                if (string.IsNullOrWhiteSpace(request.EmpCard)) throw new DataInputException("请提员工身份识别卡!");
    
                request.EmpGroup = cbxEmpGroup.Text.Trim();
    
                request.EmpName = txtName.Text.Trim();
                if (string.IsNullOrWhiteSpace(request.EmpName)) throw new DataInputException("请提供员工姓名!");
    
                request.Machine = txtStation.Text.Trim();
    
                request.Username = UserSetting.UserName.Trim();
    
                return request;
            }
            private void Post()
            {
    
                #region 
                string pn=txtPN.Text.Trim();
                var request = PreRequest(pn);
    
                Post(request);
    
                
                #endregion
    
            }
            
            private void Post(OutScanRequest request)
            {
    
                //获取定单号
                if (string.IsNullOrWhiteSpace(OrderId))
                {
                    GetOrderId();
                }
                request.OrderId = OrderId;
                request.OrderItemId = OrderItemId;
                OrderItemId++;
    
                //异步处理
                var fun = new Func<OutScanResponse>(() => { return ScanService.PostScan(request);});
                var ar=fun.BeginInvoke(null,null);
                while (!ar.IsCompleted)
                {
                    Application.DoEvents();
                    Thread.Sleep(50);
                }
                var response = fun.EndInvoke(ar);
    
                //不是同一批次
                if (!string.IsNullOrWhiteSpace(response.PlanId) && string.Compare(response.PlanId.Trim(), PlanId, true) != 0)
                {
                    PlanId = response.PlanId.Trim();
    
                    var action = new Action(() => { LoadData(); });
                    var loadDataAR = action.BeginInvoke(null, null);
                    while (!loadDataAR.IsCompleted)
                    {
                        Application.DoEvents();
                        Thread.Sleep(50);
                    }
                    
                    BindData();
                }
    
    
                if (lsvOut.Items.Count >= 1000)
                {
                    lsvOut.Items.RemoveAt(0);
                }
    
                if (response.Code == 1)
                {
    
                    lsvOut.Items.Add(new ListViewItem(new string[] { request.PN, response.MPartNo, response.MPartName, response.Amount.ToString("0.00"), "成功", "成功发送!", DateTime.Now.ToString("yy-MM-dd HH:mm:ss") }));
                    SuccessCount++;
    
                    lblSuccesTips.Text = SuccessCount.ToString();
    
    
                }
                else
                {
                    var item = lsvOut.Items.Add(new ListViewItem(new string[] { request.PN, response.MPartNo, response.MPartName, response.Amount.ToString("0.00"), "失败", response.ErrMsg, DateTime.Now.ToString("yy-MM-dd HH:mm:ss") }));
                    item.BackColor = Color.Red;
                    item.Tag = request;
                    ErrCount++;
                    lblErrTips.Text = ErrCount.ToString();
    
                }
    
    
    
                RemoveFromList(request.PN);
    
    
                lsvOut.EnsureVisible(lsvOut.Items.Count - 1);
    
               
            }
            private void GetOrderId()
            {
                var fun = new Func<string>(() => { return ScanService.GetMaxOrderId(); });
                var ar = fun.BeginInvoke(null, null);
                while (!ar.IsCompleted)
                {
                    Thread.Sleep(50);
                    Application.DoEvents();
    
                }
                OrderId = fun.EndInvoke(ar);
                OrderItemId = 1;
            }
            /// <summary>
            /// 将扫描过的记录从列表移除
            /// </summary>
            /// <param name="pn"></param>
            private void RemoveFromList(string pn)
            {
                if (ScanData == null) return;
    
    
                var row = ScanData.Table.Select(string.Format(" pfifoid='{0}'", pn)).FirstOrDefault();
                if (row != null)
                {
                    ScanData.Table.Rows.Remove(row);
                }
    
    
            }

    //==========发布配置部分============
    1.使用TopShelf方式托管WCF,结果在XPsp3的系统上老是安装不了,不过放到win2003上就正常了

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using Topshelf;
    using System.IO;
    namespace OutScanServer
    {
        using DotNetHalfGoodsHouse;
        using DotNetHalfGoodsHouse.Services;
    
        class Program
        {
            private static string EndpointStr
            {
                get
                {
                    return DotNetHalfGoodsHouse.EFModel.ModelSetting.GetSetting("ServiceEndpoint",
                        "net.tcp://192.168.1.31:8888/OutScanService");
                }
            }
            static void Main(string[] args)
            {
               
    
                var wsHost = HostFactory.New(x => {
                    x.Service<ServiceHost>(s =>
                    {
                        s.SetServiceName("配料扫描出库");
                        s.ConstructUsing(name=> new ServiceHost(typeof(OutScanService)));
                        s.WhenStarted(tc => {
                            
                            tc.AddServiceEndpoint(typeof(IOutScanService), new NetTcpBinding(SecurityMode.None), EndpointStr);
                            tc.Opened += (sObj, e) =>
                            {
                                Console.WriteLine("服务启动!");
                            };
                            tc.Open();
                        });
    
                        s.WhenStopped(tc => {
                            tc.Close();
                        });
                    });
    
    
                    x.RunAsLocalSystem();
    
                    x.StartAutomatically();
                    x.DependsOnMsSql();
                    x.SetDescription("配料扫描出库服务端!");
                    x.SetDisplayName("HaoDaOutScanService");
                    x.SetServiceName("HaoDaOutScanService");
                 
                });
    
                wsHost.Run();
      
            }
        }
    }

    2.采用VS自带的Windows Service项目也不比TopShelf麻烦多少,而且XP上也可以装,就是安装时使用installuntil 注意要使用对应.net framework版本,不然会提示程序集找不到一类的错误。

    View Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Linq;
    using System.ServiceProcess;
    using System.Text;
    using System.ServiceModel;
    namespace OutScanWinSvr
    {
        using DotNetHalfGoodsHouse;
        using DotNetHalfGoodsHouse.Services;
    
        public partial class OutScanWinSvr : ServiceBase
        {
            private ServiceHost _Host;
            public OutScanWinSvr()
            {
                InitializeComponent();
    
                #region  初始华服务
                _Host = new ServiceHost(typeof(OutScanService));
                _Host.AddServiceEndpoint(typeof(IOutScanService), new NetTcpBinding(),
                                         DotNetHalfGoodsHouse.EFModel.ModelSetting.GetSetting("ServiceEndpoint","")
                                         );
    
          
    
                
                #endregion
    
            }
    
            protected override void OnStart(string[] args)
            {
                _Host.Open();
            }
    
            protected override void OnStop()
            {
                _Host.Close();
            }
        }
    }

     WCF客户端使用BasicHttpBinding时默认开启2条TCP,要开更多需要设置

     System.Net.ServicePointManager.DefaultConnectionLimit = 512;

  • 相关阅读:
    【Ruby on Rails 学习五】Ruby语言的方法
    【Ruby on Rails 学习六】Ruby 类 的入门
    【Ruby on Rails 学习三】Ruby 基本数据类型(类、类的实例、对象)
    【深度学习笔记】第 1 课:从机器学习到深度学习
    【Ruby on Rails学习二】在线学习资料的整理
    【Ruby on Rails 学习一】ubuntu14.04配置rvm与ruby
    THREE.JS + Blender(obj、mtl加载代码)
    全站查询和分页显示——在线留言板2
    增加留言版块——在线留言板1
    html加载速度技术点
  • 原文地址:https://www.cnblogs.com/wdfrog/p/2616221.html
Copyright © 2011-2022 走看看