需要使用队列时并且涉及多线程时使用ConcurrentQueue
这个性内比自己使用Queue并且配合lock要好很多
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 = ; i < ; i++)
{
try
{ calcService.Add(, );
}
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(); //这一行会报错,
编辑窗口代码
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(,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 >= )
{
var nameValue=new PropertyNameValue();
nameValue.Name= arr[].Replace("[", "").Replace("]", "");
if (arr.Length >= )
{
nameValue.Value = arr[].Trim();
}
else
{
nameValue.Value = "";
}
ModifyProperties.Add(nameValue);
}
}
if (ModifyProperties.Count <= )
{
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实现代码
public int SetProperty(List<PropertyNameValue> properties,string position)
{
var memoryStatus = EMControlServer.Instance.GetStatus(position);
SetProperty(properties, memoryStatus);
return ;
}
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 ;
}
public int Free(EMStatusInfo status)
{
var memoryStatus = EMControlServer.Instance.GetStatus(status.Position);
if (memoryStatus.LockValue != )
{
throw new Exception("设备并未锁定");
}
EMControlServer.Instance.DoUnlockAction(status.Position);
return ;
} 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
主控窗体实现代码
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(, );
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(, );
this.listView1.TabIndex = ;
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 <= ) return;
var position = this.listView1.SelectedItems[].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[]);
hc.Text = arr[];
listView1.Columns.Add(hc);
}
for (int i = ; i <= ; i++)
{
var name = "" + i;
var position = "ZD" + name.Substring(name.Length - );
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 = ;
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[].Text = sItem.EmpNo;
lvItem.SubItems[].Text = sItem.TaskId.ToString();
lvItem.SubItems[].Text = sItem.ParentStatus;
lvItem.SubItems[].Text = sItem.Status;
lvItem.SubItems[].Text = sItem.CounterValue.ToString();
lvItem.SubItems[].Text = sItem.LockValue.ToString();
lvItem.SubItems[].Text = sItem.ValueChangeTime.ToString();
lvItem.SubItems[].Text = sItem.BCounterNum.ToString();
lvItem.SubItems[].Text = sItem.ProduceNum.ToString();
lvItem.SubItems[].Text = sItem.Amount.ToString();
lvItem.SubItems[].Text = sItem.IsCompleted.ToString();
lvItem.SubItems[].Text = sItem.DetectionRequest.ToString();
lvItem.SubItems[].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 = ; i <= ; i++)
{
var name = "" + i;
var position = "ZD" + name.Substring(name.Length - , );
list.Add(new PositionInfo() { Name = "自动机", Position = position });
}
XmlDataCfgMgr<List<PositionInfo>>.SaveV(list);
}
private static void InitWhiteList()
{
using (var ctx = DBCtx.GetZDCtlCtx())
{
for (int i = ; i <= ; i++)
{
var name = "" + i;
name = name.Substring(name.Length - );
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 = ;
for (int i = ; i <= ; i++)
{
var position = "" + i;
var no = position.Substring(position.Length - );
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+ });
clientId += ;
}
XmlDataCfgMgr< List<VariateGroupInfo>>.SaveV(list);
}
#endregion
#region Mock
private int[] countArr = new int[];
private Boolean[] lockArr = new Boolean[];
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 = ;
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();
continue;
}
var list = new List<ChangedItem>(); for (int i = ; i <= ; i++)
{
if (lockArr[i]) continue; var name = "" + i;
var position = "ZD" + name.Substring(name.Length - , );
var inNum = rand.Next();
if (inNum >= ) continue;
countArr[i] += inNum;
if (countArr[i] >= ) countArr[i] = ;
list.Add(new ChangedItem() { Name = ChangedItem.Name_Counter, Position = position, Value = countArr[i] }); } EMControlServer.Instance.HandleItemChanged(list);
Thread.Sleep();
#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 <= ) return;
var position = this.listView1.SelectedItems[].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 <= ) return;
var position = this.listView1.SelectedItems[].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
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链接
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( * * );
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 % ;
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
} }