位置设定窗口
** a: lock 函数的使用:
// lock 语法:目的是在多线程中,使用 lock 后,能使该代码块按照指定的顺序执行;当 lock 这块代码已经被其中一个线程访问时,那么另外一个线程只能等待其访问结束。 ( 增加了多线程,当我想要同时执行A、B两种方法时,AB执行的先后是不可控的(不是先执行完A或者先执行完B的不可控,是执行过程中两个方法同时进行,其中一些共同变量的调用有先后的区别),可以通过 lock 进行代码执行顺序的锁定);程序一旦进入 lock,那就锁住这段代码,此时只能有一个线程去访问,只有等这个线程访问结束了,其他线程才能访问。
private object o = new object();//创建一个对象
public void Work()
{
lock(o)//锁住这个对象
{
//做一些必须按照顺序做的事情
}
}
// lock的使用等价于
Monitor.Enter(o);
{
do
}
Monitor.Exit(o);
// 例1、
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static int a = 0;
static int b = 0;
private static object o = new object();
static void Main(string[] args)
{
//A();
//B();
Thread t1 = new Thread(A);
Thread t2 = new Thread(B);
t1.Start();
t2.Start();
Thread t3 = new Thread(C);
t3.Start();
Console.ReadLine();
}
private static void A()
{
lock (o)
{
a = a + 2;
Console.WriteLine("我是A方法,a=" + a);
Thread.Sleep(5000);//暂停5秒
b = b + 2;
Console.WriteLine("我是A方法,b=" + b);
}
}
private static void B()
{
lock (o)
{
b++;
Console.WriteLine("我是B方法,b=" + b);
Thread.Sleep(1000); //暂停1秒
a++;
Console.WriteLine("我是B方法,a=" + a);
}
}
private static void C()
{
Console.WriteLine("我是C方法,随机出现");
}
}
}
** b: 多线程的使用:
// 进程:程序在服务器上运行时占据的计算资源集合称之为进程;进程间不会相互影响或干扰,但是,进程之间的通讯比较困难(分布式);
// 线程:程序执行的最小单位,响应操做的最小的执行流;一个进程可以有多个线程(线程属于进程)并发执行;
// C#中多线程 Thread 类是 .net Frameork 对线程对象的抽象封装;通过 Thread 完成的操做,最终通过向操做系统请求得到执行流;
// currentThread : 是指当前正在运行的代码进程;
// Thread.CurrentThread.ManagedThreadId: 当前正在运行的进程的编号
// 任何的异步多线程都离不开委托 delegate —— lambda —— action / func
// 同步是按照顺序一次进行执行的,可能会导致UI界面卡住,无法拖动(主线程忙于计算,没有多余的算力更新UI); 异步执行没有顺序,并且是同时开始的,不会卡住界面;
// 由于多线程具有随机启动和不可预测性,在很多时候对业务有影响,所以使用多线程时也要解决多线程的不可预测性;
// 多线程相关的命令
// Thread、ThreadPool、Task、Async、Invoke、await
// Thread的使用方式
// 简单的线程处理功能
// 后台代码中先要建立一个线程的函数,这里命名为ThreadProc
public void ThreadProc()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadProc{0}", i);
//向外输出次数
Thread.Sleep(0);
}
}
// 然后当触发按钮之后,会创建一个新的线程并执行
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("主进程开启第二进程");
//thread 类需要一个委托函数 ThreadStart 来表示在线程上要执行的内容
//Thread t = new Thread(new ThreadStart(ThreadProc));
Thread t = new Thread(ThreadProc);
t.Start();
}
// 需要注意这里的 thread t 有两种生成的方式均可。
// 向进程函数中传入变量:上面我们可以看到,进程函数没有传入参数,如果我们需要向进程中传入参数的话,可以参照下面的代码:
public void ThreadProc(object obj)
{
for (int i = 0; i < (int)obj; i++)
{
Console.WriteLine("ThreadProc{0}", i);
//向外输出次数
Thread.Sleep(0);
}
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("主进程开启第二进程");
//thread 类需要一个委托函数 ThreadStart 来表示在线程上要执行的内容
Thread t = new Thread(ThreadProc);
t.Start(120);
}
** 1、 设置锁,防止两个模式同时进行;设置多线程委托;
// Camera.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HalconDotNet;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
using System.Xml;
namespace vision
{
public class Camera
{
//10.28ch add
public mainform mrf;
public object lockobj = new object();//锁定义,实现两个事件互斥,我进行时你等待;
public List<ImageTool> toollist;
public int mode;//模式,0内触发,1外触发预采集,2.检测模式;
public int fps;
public bool islastcam;//是否为最后一个相机
public List<bool> result = new List<bool>();//结果队列
//public List<long> rechunk = new List<long>();
public List<HWindowControl> halconwin = new List<HWindowControl>();
public string name;
public string logicName;
public HObject Image;
//****定义委托
public delegate void sentlogo(bool isok);
//private delegate void DeviceRemovedEventHandler();
public event sentlogo sentlogoEvent;
public HTuple resultHTuple;
public HObject RegionToDisp;
protected Object m_lockObject;
public HObject tempImage;
public bool isopen;
private int exposureTime;
public int rectifytype;
public int ExposureTime
{
get { return exposureTime; }
set { exposureTime = value; SetFloatSetting("ExposureTimeAbs", value); }
}
private int gain;
public int Gain
{
get { return gain; }
set { gain = value; SetIntegerSetting("Gain", value); }
}
private double pixelDist;
public double PixelDist
{
get { return pixelDist; }
set { pixelDist = value; }
}
public Camera()
{
try
{
isopen = false;
toollist = new List<ImageTool>();
resultHTuple = new HTuple();
HOperatorSet.GenEmptyObj(out RegionToDisp);
HOperatorSet.GenEmptyObj(out Image);
HOperatorSet.GenEmptyObj(out tempImage);
m_lockObject = new Object();
exposureTime = 30;
gain = 300;
pixelDist = 1;
mode = 0;
}
catch (Exception e)
{
MessageBox.Show("相机初始化失败");
}
}
public int sentcounter = 0;
public int imagecount = 0;
bool isready = true;
long lastchunk = 0;
HObject rectifymap;
public void ImageProcess()
{
try
{
if (isready)
{
isready = false;
Image.Dispose();
// HOperatorSet.CopyImage(m_imageProvider.ho_Image, out Image);
lock (lockobj)
{
// Card.stop();
//三种模式 模式,0内触发,1外触发预采集,2.检测模式;
if (mode == 0)
{
foreach (HWindowControl hwin in halconwin)
{
// HOperatorSet.ClearWindow(hwin.HalconWindow);
hwin.HalconWindow.DispObj(Image);
}
}
else if (mode == 1)
{
foreach (HWindowControl hwin in halconwin)
{
hwin.HalconWindow.DispObj(Image);
}
HOperatorSet.WriteImage(Image, "bmp", 0, pathtool.currentProductPath + "\\" + logicName + "\\" + imagecount + ".bmp");
}
else if (mode == 2)
{
//if (this.logicName == "CCD2")
//{
// Card.stop();
//}
//畸变校正
if (rectifytype == 0)
{
HOperatorSet.MapImage(Image, rectifymap, out Image);
}
///这里使用检测
bool tempresult = true;
//并按照是否为currentccd,显示左上角ok ng
if (logicName == mainform.CurrentCCD)
{
// Card.stop();
//****通过委托进行跨线程;委托定义在上边;
//此处调用主线程的invoke导致,在imageprovider里的 thread join 时候发生死锁
sentlogoEvent(tempresult);
//HObject tempim;
//HOperatorSet.GenEmptyObj(out tempim);
//HOperatorSet.DumpWindowImage(out tempim, halconwin[0].HalconWindow);
if (halconwin.Count == 2) //只让当前窗口显示的相机里有一个相机,防止两个相机产生bug;
{
halconwin[1].HalconWindow.DispObj(Image);
foreach (ImageTool tool in toollist)
{
tool.hwin = halconwin[1].HalconWindow;
tool.dispresult();
}
}
}
}
}
imagecount++;
isready = true;
}
else
{
}
}
catch (Exception e)
{
int aa = 0;
}
}
public void Open()
{
}
public void Stop()
{
}
public void InterGrab()
{
}
public void StartGrab()
{
}
public void Close()
{
}
public bool SetIntegerSetting(string Feature, int value)
{
return false;
}
public bool SetFloatSetting(string Feature, int value)
{
return false;
}
public bool SetModeFeature(string Feature, string value)
{
return false;
}
private void CameraRemovedEvent()
{
}
private void OnGrabErrorEvent(Exception grabException, string additionalErrorMessage)
{
}
public void OutPut(bool ONOFF)
{
}
public void singlegrab()
{
}
}
}
// mainform.cs
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 HalconDotNet;
using System.Xml;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.IO;
using System.Globalization;
namespace vision
{
public partial class mainform : Form
{
public List<Camera> cameras;
public static string CurrentCCD;
public Dictionary<string, Camera> CCD;
Dictionary<string, HWindowControl> findhwin = new Dictionary<string, HWindowControl>();
public static DataSet ds=new DataSet();
public DataSet posdata;
//旧配置加载
public mainform()
{
InitializeComponent();
findhwin.Clear();
findhwin.Add("CCD1", hWindowControl2);
findhwin.Add("CCD2", hWindowControl3);
findhwin.Add("CCD3", hWindowControl4);
findhwin.Add("CCD4", hWindowControl5);
findhwin.Add("CCD5", hWindowControl6);
posdata = new DataSet();
cameras = new List<Camera>();
CCD = new Dictionary<string, Camera>();
CurrentCCD = "CCD1";
loadCamera();
foreach (Camera c in cameras)
{
c.toollist = pathtool.ReadFromdat(pathtool.currentProductPath + @"\" + c.logicName + ".dat");
}
label6.Text = pathtool.currentProduct;
posdata.ReadXml(pathtool.currentProductPath + @"\Posdata.xml");
//这里可以检查控制方面的连接是否正常,相机是否正常,如果不正常就提示
InitialDataGrid(gridControl1, ds);
updatedataset();
for (int i = 0; i < gridView1.RowCount; i++)
{
gridView1.ExpandMasterRow(i);
}
this.ShowDialog();
}
//新配置
public mainform(int a)
{
InitializeComponent();
findhwin.Clear();
findhwin.Add("CCD1", hWindowControl2);
findhwin.Add("CCD2", hWindowControl3);
findhwin.Add("CCD3", hWindowControl4);
findhwin.Add("CCD4", hWindowControl5);
findhwin.Add("CCD5", hWindowControl6);
posdata = new DataSet();
cameras = new List<Camera>();
CCD = new Dictionary<string, Camera>();
CurrentCCD = "CCD1";
loadCamera();
foreach (Camera c in cameras)
{
string cpath = pathtool.currentProductPath + @"\" + c.logicName + ".dat";
pathtool.SaveTodat(c.toollist, cpath);
}
label6.Text = pathtool.currentProduct;
InitPos();
MessageBox.Show("是新建配置!");
this.ShowDialog();
}
private void loadCamera()
{
//cameras.Clear();
try
{
panel2.BackColor = Color.AliceBlue;
XmlDocument xmlDocCamera = new XmlDocument();
xmlDocCamera.Load("./Data/" + "camset.xml");
XmlNodeList xnl;
XmlNode xn;
xn = xmlDocCamera.GetElementsByTagName("Camera")[0];
xnl = xn.ChildNodes;
int i = 1;
if (cameras.Count == 0)
{
foreach (XmlNode x in xnl)
{
Camera c = new Camera();
c.logicName = "CCD" + i;
c.halconwin.Add(findhwin[c.logicName]);
c.name = x.Attributes["name"].Value;
c.ExposureTime = int.Parse(x.Attributes["ExposureTime"].Value);
c.Gain = int.Parse(x.Attributes["Gain"].Value);
c.PixelDist = double.Parse(x.Attributes["PixelDist"].Value);
c.fps = int.Parse(x.Attributes["FPS"].Value);
c.rectifytype = int.Parse(x.Attributes["type"].Value);
c.halconwin.Clear();
c.halconwin.Add(findhwin[c.logicName]);
c.sentlogoEvent += new Camera.sentlogo(changelogo);//加载每个相机时添加事件响应(加载委托)
// c.OnImageProcessedEvent += new Camera.OnImageProcessedEventHandler(OnImageProcessedEvent);
cameras.Add(c);
i++;
}
}
for (int ci = 0; ci < cameras.Count; ci++)
{
CCD.Add("CCD" + (ci + 1).ToString(), cameras[ci]);
}
CCD["CCD1"].halconwin.Add(hWindowControl1);
}
catch (Exception e)
{
MessageBox.Show("相机加载错误");
}
}
private void InitPos()
{ //新配置时候,生成一个位置全0的posdata,并写入xml
posdata = new DataSet("posdata");
DataTable dt = new DataTable("pos");
dt.Columns.Add("cam1");
dt.Columns.Add("cam2");
dt.Columns.Add("cam3");
dt.Columns.Add("cam4");
dt.Columns.Add("cam5");
dt.Columns.Add("cam6");
dt.Columns.Add("ng");
dt.Columns.Add("ok");
dt.Columns.Add("blowwidth");
dt.Columns.Add("speed");
dt.Columns.Add("cam1expo");
dt.Columns.Add("cam2expo");
dt.Columns.Add("cam3expo");
dt.Columns.Add("cam4expo");
dt.Columns.Add("cam5expo");
dt.Columns.Add("cam6expo");
dt.Columns.Add("cam1gain");
dt.Columns.Add("cam2gain");
dt.Columns.Add("cam3gain");
dt.Columns.Add("cam4gain");
dt.Columns.Add("cam5gain");
dt.Columns.Add("cam6gain");
dt.Columns.Add("dist");
DataRow row1 = dt.NewRow();
row1["cam1"] = "0";
row1["cam2"] = "0";
row1["cam3"] = "0";
row1["cam4"] = "0";
row1["cam5"] = "0";
row1["cam6"] = "0";
row1["ng"] = "1000";
row1["ok"] = "1500";
row1["blowwidth"] = "500";
row1["speed"] = "1000";
row1["cam1expo"] = "20";
row1["cam2expo"] = "20";
row1["cam3expo"] = "20";
row1["cam4expo"] = "20";
row1["cam5expo"] = "20";
row1["cam6expo"] = "20";
row1["cam1gain"] = "280";
row1["cam2gain"] = "280";
row1["cam3gain"] = "280";
row1["cam4gain"] = "280";
row1["cam5gain"] = "280";
row1["cam6gain"] = "280";
row1["dist"] = "50";
dt.Rows.Add(row1);
posdata.Tables.Add(dt);
posdata.WriteXml(pathtool.currentProductPath + @"\Posdata.xml");
}
private void button5_Click(object sender, EventArgs e)
{
Close();
}
private void button2_Click(object sender, EventArgs e)
{
Form1 setform = new Form1(this);
setform.ShowDialog();
}
private void InitialDataGrid(DevExpress.XtraGrid.GridControl grid, DataSet ds)
{
// 定义主表
DataTable masterTable = new DataTable("CameraTable");
DataTable detailTable = new DataTable("DetailTable");
DataColumn parentColumn = new DataColumn("CameraID", typeof(string));
masterTable.Columns.Add(parentColumn);
DataColumn childrenColumn = new DataColumn("CCD", typeof(string));
detailTable.Columns.Add(childrenColumn);
detailTable.Columns.AddRange(new DataColumn[] {
new DataColumn("检测项",typeof(string)),
new DataColumn("名称",typeof(string)),
new DataColumn("下限",typeof(double)),
new DataColumn("上限",typeof(double)),
new DataColumn("测量",typeof(double)),
new DataColumn("合格率",typeof(double)),
});
ds.Tables.AddRange(new DataTable[] { masterTable.Copy(), detailTable.Copy() });
// 创建表关系
DataRelation relation = new DataRelation("detailTable", ds.Tables[0].Columns[0], ds.Tables[1].Columns[0], false);
ds.Relations.Add(relation); // 添加
grid.DataSource = ds.Tables[0]; // 指定数据源
ds.Clear();
gridView1.ExpandMasterRow(0);
for (int i = 0; i < gridView1.RowCount; i++)
{
gridView1.ExpandMasterRow(i);
}
}
public void updatedataset()
{
//update写入时候,计算出当前tool的参数位置,结果显示位置,并传递给它
//
ds.Clear();
DataTable masterTable = new DataTable("CameraTable");
DataTable detailTable = new DataTable("DetailTable");
masterTable = ds.Tables["CameraTable"];
detailTable = ds.Tables["DetailTable"];
int rowcount = 0;
for (int i = 0; i < cameras.Count; i++)
{
masterTable.Rows.Add(cameras[i].logicName);
}
for (int i = 0; i < cameras.Count; i++)
{
for (int j = 0; j < cameras[i].toollist.Count; j++)
{
cameras[i].toollist[j].posdataset.Clear();
for (int k = 0; k < cameras[i].toollist[j].ischeck.Count; k++)
{
if (cameras[i].toollist[j].ischeck[k])
{
//测量名//用户自定义名 下限 上限 实际值 合格率
detailTable.Rows.Add(cameras[i].logicName, cameras[i].toollist[j].absname[k], cameras[i].toollist[j].defname[k], cameras[i].toollist[j].xx[k], cameras[i].toollist[j].sx[k], cameras[i].toollist[j].result[k], 0);
cameras[i].toollist[j].posdataset.Add(rowcount);
rowcount++;
}
}
}
}
gridView1.ExpandMasterRow(0);
for (int i = 0; i < gridView1.RowCount; i++)
{
gridView1.ExpandMasterRow(i);
}
}
private void button3_Click(object sender, EventArgs e)
{
获取日期
string SaveFileName = DateTime.Now.Date.ToString("yyyy", DateTimeFormatInfo.InvariantInfo) + DateTime.Now.Date.ToString("MM", DateTimeFormatInfo.InvariantInfo);
SaveFileName += DateTime.Now.Date.ToString("dd", DateTimeFormatInfo.InvariantInfo) + DateTime.Now.ToString("hh", DateTimeFormatInfo.InvariantInfo);
SaveFileName += DateTime.Now.ToString("mm", DateTimeFormatInfo.InvariantInfo) + DateTime.Now.ToString("ss", DateTimeFormatInfo.InvariantInfo);
string templatepath = String.Format(@"{0}\{1}", pathtool.exepath, SaveFileName);
templatepath = templatepath + "统计报表.xls";
try
{
HSSFWorkbook wk = new HSSFWorkbook();
//创建一个Sheet
ISheet sheet = wk.CreateSheet("检测结果统计");
//在第一行创建行
IRow row = sheet.CreateRow(0);
//在第一行的第一列创建单元格
ICell cell = row.CreateCell(0);
cell.SetCellValue("检测项");
cell = row.CreateCell(1);
cell.SetCellValue("自定义名称");
cell = row.CreateCell(2);
cell.SetCellValue("上限");
cell = row.CreateCell(3);
cell.SetCellValue("下限");
cell = row.CreateCell(4);
cell.SetCellValue("OK");
cell = row.CreateCell(5);
cell.SetCellValue("NG");
cell = row.CreateCell(6);
cell.SetCellValue("合格率");
合并所有tool的 goodcount badcount
List<int> allgoodcount = new List<int>();
List<int> allbadcount = new List<int>();
foreach (Camera c in cameras)
{
foreach (ImageTool t in c.toollist)
{
for (int i = 0; i < t.goodcount.Count; i++)
{
allgoodcount.Add(t.goodcount[i]);
allbadcount.Add(t.badcount[i]);
}
}
}
DataRowCollection drc = ds.Tables["detailTable"].Rows;
for (int i = 0; i < drc.Count; i++)
{
DataRow dr = drc[i];
string s = dr[1].ToString();//检测项名称
string s1 = dr[2].ToString();//自定义名称
double xx = (double)dr[3];
double sx = (double)dr[4];
double hegelv = (double)dr[6];
row = sheet.CreateRow(i + 1);
cell = row.CreateCell(0);
cell.SetCellValue(s);
cell = row.CreateCell(1);
cell.SetCellValue(s1);
cell = row.CreateCell(2);
cell.SetCellValue(xx);
cell = row.CreateCell(3);
cell.SetCellValue(sx);
cell = row.CreateCell(4);
cell.SetCellValue(allgoodcount[i]);
cell = row.CreateCell(5);
cell.SetCellValue(allbadcount[i]);
cell = row.CreateCell(6);
cell.SetCellValue(hegelv);
}
using (FileStream fs = File.OpenWrite(templatepath))
{
wk.Write(fs);//向打开的这个xls文件中写入并保存。
}
}
catch (Exception ex)
{
MessageBox.Show("报表生成发生异常");
}
}
void changelogo(bool isok) //改变标志函数;
{
try
{
if (InvokeRequired)
{
BeginInvoke(new Camera.sentlogo(changelogo), new object[] { isok });
return;
}
if (isok)
{
label1.Text = "OK";
label1.ForeColor = Color.Green;
}
else
{
label1.Text = "NG";
label1.ForeColor = Color.Red;
}
}
catch (Exception e)
{
int aa = 0;
}
}
bool ischecked = true;
public int selctedcam = 0;
private void hWindowControl2_MouseDown(object sender, MouseEventArgs e) // 防止两个窗口同时快速选中,使用 lock 方法;防止2、3窗口同时快速点击
{
if (ischecked == true)
{
ischecked = false;
if (cameras.Count > 0)
{
lock (CCD[CurrentCCD].lockobj)
{
if (CCD[CurrentCCD].halconwin.Count == 2)
{
CCD[CurrentCCD].halconwin.RemoveAt(1);
}
}
lock (CCD["CCD1"].lockobj)
{
CCD["CCD1"].halconwin.Add(hWindowControl1);
CurrentCCD = "CCD1";
}
panel2.BackColor = Color.AliceBlue;
panel3.BackColor = Color.FromArgb(60, 60, 60);
panel4.BackColor = Color.FromArgb(60, 60, 60);
panel5.BackColor = Color.FromArgb(60, 60, 60);
panel6.BackColor = Color.FromArgb(60, 60, 60);
groupControl1.Text = " CDD1 ";
selctedcam = 0;
}
}
ischecked = true;
}
private void hWindowControl3_MouseDown(object sender, MouseEventArgs e) // 防止两个窗口同时快速选中,使用 lock 方法;防止2、3窗口同时快速点击
{
if (ischecked == true)
{
ischecked = false;
if (cameras.Count > 0)
{
lock (CCD[CurrentCCD].lockobj)
{
if (CCD[CurrentCCD].halconwin.Count == 2)
{
CCD[CurrentCCD].halconwin.RemoveAt(1);
}
}
lock (CCD["CCD2"].lockobj)
{
CCD["CCD2"].halconwin.Add(hWindowControl1);
CurrentCCD = "CCD2";
}
panel2.BackColor = Color.FromArgb(60, 60, 60);
panel3.BackColor = Color.AliceBlue;
panel4.BackColor = Color.FromArgb(60, 60, 60);
panel5.BackColor = Color.FromArgb(60, 60, 60);
panel6.BackColor = Color.FromArgb(60, 60, 60);
groupControl1.Text = " CDD2 ";
selctedcam = 1;
}
}
ischecked = true;
}
}
}