需要使用队列时并且涉及多线程时使用ConcurrentQueue
这个性内比自己使用Queue并且配合lock要好很多
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
calcFactory = new ChannelFactory<ICalcService>(new BasicHttpBinding(BasicHttpSecurityMode.None), address); //tcp模式 calcFactory = new ChannelFactory<ICalcService>(new NetTcpBinding(SecurityMode.None), address); calcService = calcFactory.CreateChannel(); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10; i++) { try { calcService.Add(3, 4); } catch (Exception ex) { Console.WriteLine(ex.Message); var cObj = calcService as ICommunicationObject; if (cObj.State == CommunicationState.Faulted || cObj.State == CommunicationState.Closed || cObj.State == CommunicationState.Closing ) { Console.WriteLine("status:closed,closing,faulted"); } break; } } sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds);
tpc模式:
是如果遇到一次错误,那么会将cObj的状态改变,并且cObj对象不能再次使用
Console.WriteLine("status:closed,closing,faulted");有输出
BasicHttpBinding 无会话模式:
遇到错误后不会执行到Console.WriteLine("status:closed,closing,faulted");有输出
cObj对象可以重复使用
参考:http://www.cnblogs.com/artech/archive/2009/07/04/1516908.html
//=========类型转化==================
TypeConverter conv = TypeDescriptor.GetConverter(typeof(DateTime?));
var what = conv.ConvertFrom("");// what ==null
var whatType= what.GetType(); //这一行会报错,
编辑窗口代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using com.geelyhd.MFG.EFModel; namespace EMControlServer.UI { public partial class frmStatusEdit : Form { private EMStatusInfo MStatus; public List<PropertyNameValue> ModifyProperties = new List<PropertyNameValue>(); public frmStatusEdit() { InitializeComponent(); this.MaximizeBox = false; this.MinimizeBox = false; this.StartPosition = FormStartPosition.CenterParent; } public frmStatusEdit(EMStatusInfo it):this() { this.MStatus = it; } private void frmStatusEdit_Load(object sender, EventArgs e) { IntiList(); } private void IntiList() { checkedListBox1.CheckOnClick = true; var type= MStatus.GetType(); foreach (var p in type.GetProperties()) { if (!p.CanWrite) continue; var item = "[" +p.Name +"]" + ":" + p.GetValue(MStatus, null); checkedListBox1.Items.Add(item); } checkedListBox1.ItemCheck += (s, e) => { var item = checkedListBox1.Items[e.Index]; if (item == null) return; var itemStr=item.ToString().Trim(); var lines = textBox1.Lines; var index= itemStr.IndexOf(":"); var propertyName=itemStr.Substring(0,index); if (e.NewValue == CheckState.Checked) { var findFlag = false; foreach (var line in lines) { if (line.StartsWith(propertyName + ":")) { findFlag = true; break; } } if (!findFlag) { textBox1.Text += itemStr+Environment.NewLine; } } else if (e.NewValue == CheckState.Unchecked) { var findline=""; foreach (var line in lines) { if (line.StartsWith(propertyName + ":")) { findline=line; break; } } if (!string.IsNullOrWhiteSpace(findline)) { textBox1.Text = textBox1.Text.Replace(findline+Environment.NewLine, ""); } } }; } private void btnSubmit_Click(object sender, EventArgs e) { try { foreach (var line in textBox1.Lines) { var item = line.Trim(); var arr= item.Split(":".ToArray(), StringSplitOptions.RemoveEmptyEntries); if (arr.Length >= 1) { var nameValue=new PropertyNameValue(); nameValue.Name= arr[0].Replace("[", "").Replace("]", ""); if (arr.Length >= 2) { nameValue.Value = arr[1].Trim(); } else { nameValue.Value = ""; } ModifyProperties.Add(nameValue); } } if (ModifyProperties.Count <= 0) { throw new Exception("未提供任何变更!"); } this.DialogResult = System.Windows.Forms.DialogResult.OK; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btnCancel_Click(object sender, EventArgs e) { this.DialogResult = System.Windows.Forms.DialogResult.Cancel; } } }
WCF实现代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public int SetProperty(List<PropertyNameValue> properties,string position) { var memoryStatus = EMControlServer.Instance.GetStatus(position); SetProperty(properties, memoryStatus); return 0; } public int Persistence(string position) { var memoryStatus = EMControlServer.Instance.GetStatus(position); using (var ctx = DBCtx.GetZDCtlCtx()) { var dbStatus = ctx.EMStatus.FirstOrDefault(ent => ent.Position == position); if (dbStatus == null) throw new Exception("未发现指定机台!"); dbStatus.Amount = memoryStatus.Amount; dbStatus.BCounterNum = memoryStatus.BCounterNum; dbStatus.DetectionRequest = memoryStatus.DetectionRequest; dbStatus.EmpNo = memoryStatus.EmpNo; dbStatus.HasDetection = memoryStatus.HasDetection; dbStatus.IsCompleted = memoryStatus.IsCompleted; dbStatus.StartTime = memoryStatus.StartTime; dbStatus.TaskId = memoryStatus.TaskId; dbStatus.TaskType = memoryStatus.TaskType; ctx.SaveChanges(); } return 0; } public int Free(EMStatusInfo status) { var memoryStatus = EMControlServer.Instance.GetStatus(status.Position); if (memoryStatus.LockValue != 1) { throw new Exception("设备并未锁定"); } EMControlServer.Instance.DoUnlockAction(status.Position); return 0; } public int Ping() { return DateTime.Now.Millisecond; } #region help method private void SetProperty(List<PropertyNameValue> properties, EMStatusInfo memoryStatus) { var type = memoryStatus.GetType(); foreach (var pp in properties) { var p = type.GetProperty(pp.Name); if (!p.CanWrite) { continue; } p.SetValue(memoryStatus, TryParser(pp.Value, p.PropertyType, null), null); } } private static Object TryParser(string v, Type type, object dValue) { if (string.IsNullOrEmpty(v)) { return dValue; } else { if (type.Equals(typeof(String))) return v; var t = Activator.CreateInstance(type); try { if (t == null)//可空类型 { TypeConverter conv = TypeDescriptor.GetConverter(type); t = conv.ConvertFrom(v); } else { t = Convert.ChangeType(v, type); } } catch { t = dValue; } return t; } } #endregion
主控窗体实现代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using F.Studio.Infrastructure; using com.geelyhd.MFG.EFModel; using com.geelyhd.MFG.IService; using EMControlServer.IService; using System.ServiceModel; using System.Configuration; using F.Studio.Common.Cfg; using System.Threading; using System.Diagnostics; using System.IO; namespace EMControlServer.UI { public partial class frmMain : Form { private OPCAutoMgr OPCManager = new OPCAutoMgr(); private List<EMStatusInfo> MemoryStatus = null; private System.Windows.Forms.ListView listView1; public frmMain() { InitializeComponent(); btnServerSwitch.Text = "启动服务"; InitListView(); #region 模拟数据 //MockConfig(); #endregion EMControlServer.Instance.SetIOFunc = OPCManager.WriteIO; } private void InitListView() { #region 设置属性 listView1 = new ListViewNF(); this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; this.listView1.Location = new System.Drawing.Point(0, 0); this.listView1.Name = "listView1"; this.listView1.Size = new System.Drawing.Size(954, 296); this.listView1.TabIndex = 0; this.listView1.UseCompatibleStateImageBehavior = false; this.listView1.View = System.Windows.Forms.View.Details; this.listView1.MultiSelect = false; this.listView1.MouseDoubleClick += (s, e) => { ActionDetail(); }; this.listView1.MouseClick += (s, e) => { if (this.listView1.SelectedItems.Count <= 0) return; var position = this.listView1.SelectedItems[0].Text; if (e.Button == System.Windows.Forms.MouseButtons.Right) { contextMenuStrip1.Show(listView1,e.Location); } }; panel2.Controls.Add(listView1); #endregion listView1.View = View.Details; listView1.FullRowSelect = true; listView1.GridLines = true; listView1.BeginUpdate(); //创建头部 foreach (var item in new String[] { "机台$100", "员工$100", "任务号$100","主状态$80", "状态$150", "读数$100", "锁定$60", "更新时间$180", "开始读数$80", "批次计数$80","任务量$80","完工$60","需要检测$80","已检$60" }) { var arr = item.Split("$".ToArray(), StringSplitOptions.RemoveEmptyEntries); var hc = new ColumnHeader(); hc.Width = int.Parse(arr[1]); hc.Text = arr[0]; listView1.Columns.Add(hc); } for (int i = 1; i <= 150; i++) { var name = "00" + i; var position = "ZD" + name.Substring(name.Length - 3); var lvItem = listView1.Items.Add(position); lvItem.SubItems.AddRange( new string[] { "-","-","-", "-","-", "-","-","-","-","-","-","-","-" }); } listView1.EndUpdate(); } protected override void OnClosed(EventArgs e) { EMCServiceHost.Instance.Stop(); EMControlServer.Instance.Stop(); OPCManager.Stop(); base.OnClosed(e); } private bool CanCloseFlag=false; protected override void OnClosing(CancelEventArgs e) { if (!CanCloseFlag) { e.Cancel = true; MessageBox.Show("不允许直接关闭系统!","警告",MessageBoxButtons.OK,MessageBoxIcon.Warning); } base.OnClosing(e); } private void menuExit_Click(object sender, EventArgs e) { CanCloseFlag = true; this.Close(); Application.Exit(); } private void btnServerSwitch_Click(object sender, EventArgs e) { try { if (btnServerSwitch.Text == "启动服务") { EMCServiceHost.Instance.Start(); EMControlServer.Instance.Start(); OPCManager.Start(); var initReads= OPCManager.ReadManual(); EMControlServer.Instance.SetInitValue(initReads); timerRefresh.Enabled = true; MemoryStatus = null; btnServerSwitch.Text = "停止服务"; tips.Text = "服务启动:" + DateTime.Now; IsRunning = true; } else { EMCServiceHost.Instance.Stop(); EMControlServer.Instance.Stop(); OPCManager.Stop(); btnServerSwitch.Text = "启动服务"; timerRefresh.Enabled = false; tips.Text = "服务关闭"; IsRunning = false; //var counter = countArr.Aggregate("", (s, v) => { return s += v + ","; }).TrimEnd(",".ToCharArray()); //File.WriteAllText(@"C:c.txt", counter); } } catch (Exception ex) { MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); try { btnServerSwitch.Text = "启动服务"; EMCServiceHost.Instance.Stop(); EMControlServer.Instance.Stop(); timerRefresh.Enabled = false; IsRunning = false; } catch { } } } private Dictionary<String, RefreshItemInfo> ItemRefreshTime = new Dictionary<string, RefreshItemInfo>(); private void timerRefresh_Tick(object sender, EventArgs e) { if (!ckbAutoRefresh.Checked) return; listView1.BeginUpdate(); try { timerRefresh.Enabled = false; if (MemoryStatus == null) { MemoryStatus = EMControlServer.Instance.GetStatus(); } var c = 0; foreach (var sItem in MemoryStatus) { //"机台","员工","任务号","状态","读数","锁定" ,"更新时间" #region 刷新状态 var needFresh = false; if (!ItemRefreshTime.ContainsKey(sItem.Position)) { ItemRefreshTime[sItem.Position] = new RefreshItemInfo() { LastChangeTime = sItem.ValueChangeTime.Value, ParentStatus = sItem.ParentStatus }; needFresh = true; } if (sItem.ValueChangeTime.Value != ItemRefreshTime[sItem.Position].LastChangeTime || sItem.ParentStatus!=ItemRefreshTime[sItem.Position].ParentStatus ) { ItemRefreshTime[sItem.Position].LastChangeTime = sItem.ValueChangeTime.Value; ItemRefreshTime[sItem.Position].ParentStatus = sItem.ParentStatus; needFresh = true; } if (needFresh) { #region 逐条更新 var lvItem = listView1.FindItemWithText(sItem.Position); lvItem.SubItems[1].Text = sItem.EmpNo; lvItem.SubItems[2].Text = sItem.TaskId.ToString(); lvItem.SubItems[3].Text = sItem.ParentStatus; lvItem.SubItems[4].Text = sItem.Status; lvItem.SubItems[5].Text = sItem.CounterValue.ToString(); lvItem.SubItems[6].Text = sItem.LockValue.ToString(); lvItem.SubItems[7].Text = sItem.ValueChangeTime.ToString(); lvItem.SubItems[8].Text = sItem.BCounterNum.ToString(); lvItem.SubItems[9].Text = sItem.ProduceNum.ToString(); lvItem.SubItems[10].Text = sItem.Amount.ToString(); lvItem.SubItems[11].Text = sItem.IsCompleted.ToString(); lvItem.SubItems[12].Text = sItem.DetectionRequest.ToString(); lvItem.SubItems[13].Text = sItem.HasDetection.ToString(); #endregion c++; } #endregion } Console.WriteLine("变动数:" + c); } catch { } finally { timerRefresh.Enabled = true; } listView1.EndUpdate(); } private void frmMain_Load(object sender, EventArgs e) { //InitVariates(); } #region Helper private void CreatePositionFile() { var list = new List<PositionInfo>(); for (int i = 1; i <= 150; i++) { var name = "00" + i; var position = "ZD" + name.Substring(name.Length - 3, 3); list.Add(new PositionInfo() { Name = "自动机", Position = position }); } XmlDataCfgMgr<List<PositionInfo>>.SaveV(list); } private static void InitWhiteList() { using (var ctx = DBCtx.GetZDCtlCtx()) { for (int i = 1; i <= 150; i++) { var name = "00" + i; name = name.Substring(name.Length - 3); var wEnt = new EMWhiteList(); wEnt.AddTime = DateTime.Now; wEnt.Position = "ZD" + name; ctx.EMWhiteList.AddObject(wEnt); } ctx.SaveChanges(); } } private static void InitVariates() { var list = new List<VariateGroupInfo>(); var group = new VariateGroupInfo(); group.Name = "测试组"; list.Add(group); int clientId = 1; for (int i = 1; i <= 150; i++) { var position = "00" + i; var no = position.Substring(position.Length - 3); var pathCounter = "S71200.Control1.00" + no; var pathLock = "S71200.Control1.01" + no; position = "ZD" +no; group.Variates.Add(new VariateInfo() { Name = "计数器", Path =pathCounter, Position = position, ClientId = clientId }); group.Variates.Add(new VariateInfo() { Name = "锁定位", Path = pathLock, Position = position, ClientId = clientId+1 }); clientId += 2; } XmlDataCfgMgr< List<VariateGroupInfo>>.SaveV(list); } #endregion #region Mock private int[] countArr = new int[151]; private Boolean[] lockArr = new Boolean[151]; private Boolean IsRunning = false; private void MockConfig() { var rand = new Random(DateTime.Now.Second); if (File.Exists(@"C:c.txt")) { var nums = File.ReadAllText(@"C:c.txt"); var numArr = nums.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var j = 0; foreach (var num in numArr) { countArr[j] = int.Parse(num); j++; } } ThreadPool.QueueUserWorkItem((o) => { while (true) { Stopwatch sw = new Stopwatch(); sw.Start(); #region if (!IsRunning) { Thread.Sleep(500); continue; } var list = new List<ChangedItem>(); for (int i = 1; i <= 150; i++) { if (lockArr[i]) continue; var name = "00" + i; var position = "ZD" + name.Substring(name.Length - 3, 3); var inNum = rand.Next(6); if (inNum >= 3) continue; countArr[i] += inNum; if (countArr[i] >= 30000) countArr[i] = 0; list.Add(new ChangedItem() { Name = ChangedItem.Name_Counter, Position = position, Value = countArr[i] }); } EMControlServer.Instance.HandleItemChanged(list); Thread.Sleep(500); #endregion sw.Stop(); // Console.WriteLine(sw.ElapsedMilliseconds); } }, null); } #endregion private void menuUpdate_Click(object sender, EventArgs e) { ActionUpdate(); } private void btnRefresh_Click(object sender, EventArgs e) { ItemRefreshTime.Clear(); } private void menu_View_Click(object sender, EventArgs e) { ActionDetail(); } private void menu_Edit_Click(object sender, EventArgs e) { ActionUpdate(); } private void ActionUpdate() { if (this.listView1.SelectedItems.Count <= 0) return; var position = this.listView1.SelectedItems[0].Text; if (MemoryStatus != null) { var it = MemoryStatus.FirstOrDefault(ent => ent.Position == position); if (it != null) { using (var frm = new frmStatusEdit(it)) { if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK) { try { var list = frm.ModifyProperties; var tip = ""; EMCServerWrapper.Instance.Server.SetProperty(list, position); tip = "内存状态变更成功"; if (frm.ckbPersistence.Checked) { EMCServerWrapper.Instance.Server.Persistence(position); tip += ",持久化到数据库成功"; } MessageBox.Show(tip + "!"); } catch (Exception ex) { MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } } } private void ActionDetail() { if (this.listView1.SelectedItems.Count <= 0) return; var position = this.listView1.SelectedItems[0].Text; if (MemoryStatus != null) { var it = MemoryStatus.FirstOrDefault(ent => ent.Position == position); if (it != null) { using (var frm = new frmStatusDetail(it)) { frm.ShowDialog(); } } } } } public class EMCServerWrapper { private static readonly EMCServerWrapper _Instance = new EMCServerWrapper(); public static EMCServerWrapper Instance { get { return _Instance; } } private IEMCService _proxy; public IEMCService Server { 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; } } private class WCFHelper { private static ChannelFactory<IEMCService> _channelFac; public static ChannelFactory<IEMCService> Factory { get { if (_channelFac == null) { _channelFac = new ChannelFactory<IEMCService>(new NetTcpBinding(SecurityMode.None), EndpointStr); } return _channelFac; } } private static string EndpointStr { get { return ConfigurationManager.AppSettings["EMCServiceURL"]; } } } } public class RefreshItemInfo { public String ParentStatus { get; set; } public DateTime LastChangeTime { get; set; } } }
无刷新ListView
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; namespace com.geelyhd.MFG.UI { class ListViewNF : System.Windows.Forms.ListView { public ListViewNF() { // 开启双缓冲 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); // Enable the OnNotifyMessage event so we get a chance to filter out // Windows messages before they get to the form's WndProc this.SetStyle(ControlStyles.EnableNotifyMessage, true); } protected override void OnNotifyMessage(Message m) { //Filter out the WM_ERASEBKGND message if (m.Msg != 0x14) { base.OnNotifyMessage(m); } } } }
采用链接池管理net.tcp链接
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using EMControlServer.IService; using System.Configuration; using com.geelyhd.MFG.EFModel; using System.Collections.Concurrent; using System.Timers; namespace com.geelyhd.MFG.Service { public class EMCServerWrapper : IDisposable { private static readonly EMCServerWrapper _Instance = new EMCServerWrapper(); public static EMCServerWrapper Instance { get { return _Instance; } } private Timer HBTimer = new Timer(1000 * 60 * 2); private volatile bool Enabled = true; private ConcurrentDictionary<int, IEMCService> ProxyDic = new ConcurrentDictionary<int, IEMCService>(); private EMCServerWrapper() { #region 心跳检测 HBTimer.AutoReset = false; HBTimer.Elapsed += (s, e) => { try { var list = ProxyDic.Select(ent => new { ent.Key, ent.Value }).ToList(); foreach (var item in list) { try { item.Value.Ping(); } catch { IEMCService outIt = null; ProxyDic.TryRemove(item.Key, out outIt); try { (outIt as ICommunicationObject).Close(); } catch { } } } } catch { } finally { if (Enabled) HBTimer.Start(); } }; HBTimer.Start(); #endregion } public IEMCService Server { get { var key = DateTime.Now.Millisecond % 5; IEMCService _proxy = null; ProxyDic.TryGetValue(key, out _proxy); lock (this) { if (_proxy == null) { TryOpenChannel(ref _proxy); try { ProxyDic[key] = _proxy; } catch { } } else { var cObj = _proxy as ICommunicationObject; if (cObj.State == CommunicationState.Faulted || cObj.State == CommunicationState.Closed || cObj.State == CommunicationState.Closing ) { TryOpenChannel(ref _proxy); try { ProxyDic[key] = _proxy; } catch { } } } } return _proxy; } } private void TryOpenChannel(ref IEMCService _proxy) { try { _proxy = WCFHelper.Factory.CreateChannel(); (_proxy as ICommunicationObject).Open(); } catch (Exception) { _proxy = null; throw; } } private class WCFHelper { private static ChannelFactory<IEMCService> _channelFac; public static ChannelFactory<IEMCService> Factory { get { if (_channelFac == null) { _channelFac = new ChannelFactory<IEMCService>(new NetTcpBinding(SecurityMode.None), EndpointStr); } return _channelFac; } } private static string EndpointStr { get { return ConfigurationManager.AppSettings["EMCServiceURL"]; } } } private void Stop() { Enabled = false; try { HBTimer.Dispose(); } catch { } try { var list = ProxyDic.Select(ent => ent.Value).ToList(); foreach (var item in list) { try { (item as ICommunicationObject).Close(); } catch { } } } catch { } } #region IDisposable Members private bool disposed = false; /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed /// and unmanaged resources; <c>false</c> /// to release only unmanaged resources. /// </param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { try { Stop(); } catch { } } disposed = true; } } #endregion } }