多线程之TextBox.CheckForIllegalCrossThreadCalls = false;//消除对textbox控件的线程检测

本文通过C#示例代码介绍了如何在一个Windows Forms应用中实现多线程方法的重入,演示了两个线程同时修改同一个文本框的内容,并讨论了线程安全问题。

 

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 System.Threading;

namespace _03多线程方法重入
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;//消除对textbox控件的线程检测
        }

        /// <summary>
        /// 修改文本框的内容
        /// </summary>
        void ChangeTxt()
        {
            for (int i = 0; i < 1000; i++)
            {
                int a = int.Parse(textBox1.Text);//取到文本框中的值,已经设置文本框的处置值为0,因为这里使用到UI主线程的
                //创建的TextBox控件的实例textBox1,要想操作这个线程的话就需要在UI线程初始化的时候消除对这个控件的线程检测
                Console.WriteLine(Thread.CurrentThread.Name+",a"+a+",i="+i.ToString());//打印当前线程名字做标记
                a++;
                textBox1.Text = a.ToString();
            }
        }

        //方法重入问题
        private void btnMultiMethod_Click(object sender, EventArgs e)
        {
            //ChangeTxt();//UI线程自己访问可以通过

            Thread th = new Thread(ChangeTxt);//得到一个线程对象
            th.Name="myTh1";
            th.Priority = ThreadPriority.Highest;
            th.IsBackground = true;//把线程设置为后台线程
            th.Start();//在CPU中标记开启线程

            Thread th2 = new Thread(ChangeTxt);//得到一个线程对象
            th2.Priority = ThreadPriority.Normal;
            th2.Name = "myTh2";
            th2.IsBackground = true;//把线程设置为后台线程
            th2.Start();//在CPU中标记开启线程

        }
    }
}

 

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using VisionCCD; namespace visionPro项目练习 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //设置清空日志按钮颜色,点击时变为绿色,松开时颜色恢复 button_清空日志.MouseUp += (sender, e) => { button_清空日志.BackColor = Color.White; }; button_清空日志.MouseDown += (sender, e) => { button_清空日志.BackColor = Color.Green; }; //当鼠标悬停在按钮上时,改变背景颜色 button_清空日志.MouseEnter += (sender, e) => { button_清空日志.BackColor = Color.BlueViolet; }; button_清空日志.MouseLeave += (sender, e) => { button_清空日志.BackColor = Color.BlueViolet; }; button_清空日志.MouseEnter += (sender, e) => { button_清空日志.BackColor = Color.BlueViolet; }; button_清空日志.MouseLeave += (sender, e) => { button_清空日志.BackColor = Color.White; }; //设置打开文件按钮颜色,点击时变为绿色,松开时颜色恢复 button_openFile.MouseEnter += (sender, e) => { button_openFile.BackColor = Color.BlueViolet; }; button_openFile.MouseLeave += (sender, e) => { button_openFile.BackColor = Color.BlueViolet; }; button_openFile.MouseEnter += (sender, e) => { button_openFile.BackColor = Color.BlueViolet; }; button_openFile.MouseLeave += (sender, e) => { button_openFile.BackColor = Color.White; }; //设置打开文件按钮颜色,点击时变为绿色,松开时颜色恢复 button_openFile.MouseUp += (sender, e) => { button_openFile.BackColor = Color.White; }; button_openFile.MouseDown += (sender, e) => { button_openFile.BackColor = Color.Green; }; //设置保存文件按钮颜色,点击时变为绿色,松开时颜色恢复 button_File.MouseEnter += (sender, e) => { button_File.BackColor = Color.BlueViolet; }; button_File.MouseLeave += (sender, e) => { button_File.BackColor = Color.BlueViolet; }; button_File.MouseEnter += (sender, e) => { button_File.BackColor = Color.BlueViolet; }; button_File.MouseLeave += (sender, e) => { button_File.BackColor = Color.White; }; //设置显示按钮颜色,点击时变为绿色,松开时颜色恢复 button_display.MouseUp += (sender, e) => { button_display.BackColor = Color.White; }; button_display.MouseDown += (sender, e) => { button_display.BackColor = Color.Green; }; button_display.MouseEnter += (sender, e) => { button_display.BackColor = Color.BlueViolet; }; button_display.MouseLeave += (sender, e) => { button_display.BackColor = Color.BlueViolet; }; button_display.MouseEnter += (sender, e) => { button_display.BackColor = Color.BlueViolet; }; button_display.MouseLeave += (sender, e) => { button_display.BackColor = Color.White; }; //设置控件按钮颜色,点击时变为绿色,松开时颜色恢复 button_控件.MouseUp += (sender, e) => { button_控件.BackColor = Color.White; }; button_控件.MouseDown += (sender, e) => { button_控件.BackColor = Color.Green; }; button_控件.MouseUp += (sender, e) => { button_控件.BackColor = Color.White; }; button_控件.MouseDown += (sender, e) => { button_控件.BackColor = Color.Green; }; //设置控件按钮颜色,点击时变为绿色,松开时颜色恢复 button_控件.MouseEnter += (sender, e) => { button_控件.BackColor = Color.BlueViolet; }; button_控件.MouseLeave += (sender, e) => { button_控件.BackColor = Color.BlueViolet; }; button_控件.MouseEnter += (sender, e) => { button_控件.BackColor = Color.BlueViolet; }; button_控件.MouseLeave += (sender, e) => { button_控件.BackColor = Color.White; }; //设置控件按钮颜色,点击时变为绿色,松开时颜色恢复 button_控件.MouseUp += (sender, e) => { button_控件.BackColor = Color.White; }; button_控件.MouseDown += (sender, e) => { button_控件.BackColor = Color.Green; }; //设置button_客户端按钮颜色,点击时变为绿色,松开时颜色恢复 button_客户端.MouseEnter += (sender, e) => { button_客户端.BackColor = Color.BlueViolet; }; button_客户端.MouseLeave += (sender, e) => { button_客户端.BackColor = Color.BlueViolet; }; button_客户端.MouseEnter += (sender, e) => { button_客户端.BackColor = Color.BlueViolet; }; button_客户端.MouseLeave += (sender, e) => { button_客户端.BackColor = Color.White; }; //设置button_客户端按钮颜色,点击时变为绿色,松开时颜色恢复 button_客户端.MouseUp += (sender, e) => { button_客户端.BackColor = Color.White; }; button_客户端.MouseDown += (sender, e) => { button_客户端.BackColor = Color.Green; }; } private void Form1_Load(object sender, EventArgs e) { danlimoshi.Instance.SetToolBlock(cogToolBlockEditV21, RecordDisplay); } private void button1_Click(object sender, EventArgs e) { danlimoshi.Instance.SaveToolBlock(); } private void button2_Click(object sender, EventArgs e) { danlimoshi.Instance.Run(); ClassFustion.SaveText("当前用户点击拍照" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n", text: textBox1); } // 添加保存文件方法 private void button_File_Click(object sender, EventArgs e) { using (SaveFileDialog saveDialog = new SaveFileDialog()) { saveDialog.Filter = "日志文件|*.log|文本文件|*.txt|所有文件|*.*"; saveDialog.Title = "保存日志文件"; saveDialog.DefaultExt = ".log"; // 设置初始值 string lastPath = ClassFustion.GetPersistedLogPath(); if (!string.IsNullOrEmpty(lastPath)) { saveDialog.InitialDirectory = Path.GetDirectoryName(lastPath); saveDialog.FileName = Path.GetFileName(lastPath); } if (saveDialog.ShowDialog() == DialogResult.OK) { // 导出日志 ClassFustion.ExportLog(textBox1.Text, saveDialog.FileName); // 记录最新路径 ClassFustion.PersistLogPath(saveDialog.FileName); // 记录操作日志 ClassFustion.SaveText($"日志已保存到: {saveDialog.FileName}", text: textBox1); } } } // 添加打开文件方法 private void button_openFile_Click(object sender, EventArgs e) { using (OpenFileDialog openDialog = new OpenFileDialog()) { openDialog.Filter = "日志文件|*.log;*.txt|所有文件|*.*"; openDialog.Title = "打开日志文件"; // 设置初始目录 string lastPath = ClassFustion.GetPersistedLogPath(); if (!string.IsNullOrEmpty(lastPath)) { openDialog.InitialDirectory = Path.GetDirectoryName(lastPath); } if (openDialog.ShowDialog() == DialogResult.OK) { // 加载日志 string logContent = ClassFustion.LoadLog(openDialog.FileName); if (!string.IsNullOrEmpty(logContent)) { textBox1.Text = logContent; ClassFustion.SaveText($"已加载日志: {openDialog.FileName}", text: textBox1); } } } } private void button_清空日志_Click(object sender, EventArgs e) { textBox1.Text = ""; } private void button1_Click_1(object sender, EventArgs e) { Face face = new Face(); face.Show(); } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using communication; namespace VisionCCD { [Serializable] /// <summary> /// 通讯页面类 /// </summary> public partial class Face : Form { #region 变量 Thread th = null; SockServer servers; #endregion #region 单例模式 private static Face single = null; /// <summary> /// 通讯界面单例 /// </summary> public static Face Single { get { if (single == null) { single = new Face(); } return single; } } #endregion #region 设计窗体 /// <summary> /// 该类被实例化第1就调用此方法 /// </summary> public Face() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false;//线程访问 } /// <summary> /// 该方法等.show()被调用之后,程序就会调用Form1_Load,为第2步 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { } /// <summary> /// 该方法等程序被关闭时,Form1_FormClosing被调用,为第“最后一步” /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_FormClosing(object sender, FormClosingEventArgs e) { //System.Diagnostics.Process tt = System.Diagnostics.Process.GetProcessById(System.Diagnostics.Process.GetCurrentProcess().Id); //tt.Kill(); this.Hide(); e.Cancel = true; } #endregion #region TCP客户端 #region 客户端变量 #region 设置标定变量 private string tcp_Send; /// <summary> /// 标定发送表头 /// </summary> public string Tcp_Send { get { return tcp_Send; } set { if (value != null && value.Length > 0) { tcp_Send = value; } } } private int tcp_SplitHead; /// <summary> /// 起始字符 /// </summary> public int Tcp_SplitHead { get { return tcp_SplitHead; } set { if (value != null && value.ToString().Length > 0) { tcp_SplitHead = value; } } } private int tcp_SplitLengt; /// <summary> /// 字符长度 /// </summary> public int Tcp_SplitLengt { get { return tcp_SplitLengt; } set { if (value != null && value.ToString().Length > 0) { tcp_SplitLengt = value; } } } private string tcp_SplitStr; /// <summary> /// 字符 /// </summary> public string Tcp_SplitStr { get { return tcp_SplitStr; } set { if (value != null && value.Length > 0) { tcp_SplitStr = value; } } } private char[] tcp_Index; /// <summary> /// 截取数据 /// </summary> public char[] Tcp_Index { get { return tcp_Index; } set { if (value != null && value.Length > 0) { tcp_Index = value; } } } #endregion #region 设置定位变量 private string tcp_SendS; public string Tcp_SendS { get { return tcp_SendS; } set { if (value != null && value.Length > 0) { tcp_SendS = value; } } } private int tcp_SplitHeadS; public int Tcp_SplitHeadS { get { return tcp_SplitHeadS; } set { if (value != null && value.ToString().Length > 0) { tcp_SplitHeadS = value; } } } private int tcp_SplitLengtS; public int Tcp_SplitLengtS { get { return tcp_SplitLengtS; } set { if (value != null && value.ToString().Length > 0) { tcp_SplitLengtS = value; } } } private string tcp_SplitStrS; public string Tcp_SplitStrS { get { return tcp_SplitStrS; } set { if (value != null && value.Length > 0) { tcp_SplitStrS = value; } } } #endregion #endregion /// <summary> /// 通讯接收消息 /// </summary> /// <param name="value"></param> private void XingHao(string value) { try { if (value.Length >= 0) { ClientDataShow.AppendText(value + "\r\n"); } } catch (Exception ex) { MessageBox.Show("接收信号失败:" + ex.Message); } } #endregion #region 客户端 //链接按钮 private void button4_Click(object sender, EventArgs e) { SockClient.Single.Connect(ClinetIP.Text,Convert.ToInt16(ClientPort.Text)); SockClient.Single.del -= XingHao; SockClient.Single.del += XingHao; } //关闭按钮 private void button6_Click(object sender, EventArgs e) { SockClient.Single.Close();//关闭连接 this.Close();//关闭窗口 } //发送按钮 private void button3_Click(object sender, EventArgs e) { SockClient.Single.Send(textBox5.Text); MessageBox.Show("发送成功"); } #endregion //修改按钮 private void BT_DataSplit_Click(object sender, EventArgs e) { try { Tcp_Send = ClinetSendTex.Text;//标定发送表头 Tcp_SplitHead = Convert.ToInt16(CB_SplitHead.Text);//起始字符 Tcp_SplitLengt = Convert.ToInt16(CB_SplitLengt.Text);//字符长度 Tcp_SplitStr = TB_SplitStr.Text;//字符 char[] lo1 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Index1.Text));//截取数据_索引 char[] lo2 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Index2.Text)); char[] lo3 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Word_X1.Text));//截取数据_Word_X char[] lo4 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Word_X2.Text)); char[] lo5 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Word_Y1.Text));//截取数据_Word_Y char[] lo6 = Encoding.Default.GetChars(Encoding.Default.GetBytes(TB_Word_Y2.Text)); char[] JiLu = new char[6]; JiLu[0] = lo1[0]; JiLu[1] = lo2[0]; JiLu[2] = lo3[0]; JiLu[3] = lo4[0]; JiLu[4] = lo5[0]; JiLu[5] = lo6[0]; Tcp_Index = JiLu;//截取数据 Tcp_SplitHeadS = Convert.ToInt16(comboBox3.Text); Tcp_SplitLengtS = Convert.ToInt16(comboBox2.Text); Tcp_SplitStrS = textBox6.Text; Tcp_SendS = textBox7.Text; } catch (Exception ex) { MessageBox.Show("交互设置异常:" + ex.Message); } } #region TCP服务器 //服务器链接按钮 private void button1_Click(object sender, EventArgs e) { servers = new SockServer(); servers.CreateSever(IpAddres.Text,Convert.ToInt16(PortAddres.Text)); } //关闭按钮 private void button2_Click(object sender, EventArgs e) { servers.Send(SendTex.Text); } //发送按钮 private void button5_Click(object sender, EventArgs e) { servers.Close(); } #endregion } } using Cognex.VisionPro; using Cognex.VisionPro.CalibFix; using Cognex.VisionPro.Caliper; using Cognex.VisionPro.PMAlign; using Cognex.VisionPro.ToolBlock; using communication; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Documents; using System.Windows.Forms; namespace visionPro项目练习 { public class danlimoshi { //定义一个单例模式 private static danlimoshi instance = null; CogToolBlockEditV2 _toolBlock = null; CogToolBlock Block = null; int indexs; double x;double y; CogRecordDisplay cogRecordDisplay1; string biaotou = null; public static danlimoshi Instance { get { if (instance == null) { instance = new danlimoshi(); } return instance; } } public void SetToolBlock(CogToolBlockEditV2 toolBlock, CogRecordDisplay cogRecordDisplay1) { Block = CogSerializer.LoadObjectFromFile(Application.StartupPath + "\\File\\PAM.vpp") as CogToolBlock; this._toolBlock = toolBlock; this._toolBlock.Subject = null; this._toolBlock.Subject = Block; this.cogRecordDisplay1 = cogRecordDisplay1; Block.Ran += Block_Ran; SockClient.Single.del += GetTCPdate; } private void Block_Ran(object sender, EventArgs e) { cogRecordDisplay1.Image = (ICogImage)Block.Outputs[0].Value; // 获取输出图像 cogRecordDisplay1.Record = Block.CreateLastRunRecord(); // 获取运行记录 // 图像自适应 cogRecordDisplay1.Fit(false); // 不保持比例 CogPMAlignTool pmAlignTool = Block.Tools["CogPMAlignTool1"] as CogPMAlignTool;//获取圆检测工具 //判断圆是否被检测到 if (pmAlignTool.Results.Count > 0) { CreateLabel(0, 0, "模版匹配成功!"); CogFindCircleTool cfc = Block.Tools["CogFindCircleTool1"] as CogFindCircleTool; if (cfc.Results!=null && cfc.Results.GetCircle()!=null) { //找圆成功 CreateLabel(0, 100, "找圆成功!"); if (biaotou == "Calib") { Calib(indexs, cfc.Results.GetCircle().CenterX, cfc.Results.GetCircle().CenterY,x, y); } else if (biaotou == "CameraS1") { string val = "CameraOK:" + cfc.Results.GetCircle().CenterX + "," + cfc.Results.GetCircle().CenterY + "#0$"; SockClient.Single.Send(val); ClassFustion.SaveText("发送信号:"+val); } } else { //找圆失败 CreateLabel(0, 100, "找圆失败!", false); } } else { CreateLabel(0, 0, "圆检测失败!", false); } biaotou = null;//清空标志位 } //获得通讯TCP private void GetTCPdate(string vule) { ClassFustion.SaveText("收到信号:"+vule); if (vule.Substring(0,5) == "Calib")//判断是否为校准数据 { biaotou = "Calib"; indexs =Convert.ToInt16( vule.Split(':')[1].Split(';')[0] );//获取圆心索引号 x = Convert.ToDouble(vule.Split(';')[1].Split(',')[0]);//获取圆心X坐标 y = Convert.ToInt16(vule.Split(',')[1].Split('#')[0]);//获取圆心Y坐标 Block.Run();//执行拍照 } if (vule.Substring(0,8) == "CameraS1" ) { //判断是否为“定位表头” biaotou = "CameraS1"; Run();//执行拍照 } } /// <summary> /// 创建标签方法 /// </summary> /// public void CreateLabel(double x, double y, string text, bool Color = true) { //创建标签 CogGraphicLabel label = new CogGraphicLabel(); //设置标签字体大小 label.Font = new System.Drawing.Font("Arial", 15); if (Color) { //设置字体颜色 label.Color = CogColorConstants.Green; } else { label.Color = CogColorConstants.Red; } //设置对齐方式 label.Alignment = CogGraphicLabelAlignmentConstants.TopLeft; //显示文字内容和位置 label.SetXYText(x, y, text); //将标签显示在图形上 this.cogRecordDisplay1.InteractiveGraphics.Add(label, "CogImageConvertTool1.OutputImage", true); } //创建一个方法,将工具块保存到文件 public void SaveToolBlock() { //获取工具块内容 CogToolBlock vppToolBlock = this._toolBlock.Subject; //保存文件 CogSerializer.SaveObjectToFile(vppToolBlock, Application.StartupPath + "\\File\\PAM.vpp"); } //创建一个run方法,将图片显示在RecordDisplay上 public void Run() { //运行工具块 Block.Run(); } //这里创建一个九点标定方法,对应的坐标进行标定 public void Calib(int index,double pixel_x,double pixel_y,double Robot_x, double Robot_y) { //获取校准点到点工具 index -= 1; CogCalibNPointToNPointTool calib = Block.Tools["CogCalibNPointToNPointTool1"] as CogCalibNPointToNPointTool; //未校正XY坐标,数据传入接口 calib.Calibration.SetUncalibratedPoint(8-index, pixel_x, pixel_y); //原始坐标,数据传入接口 calib.Calibration.SetRawCalibratedPoint(index, Robot_x, Robot_y); if (index >= 8) { //标定完成标定 calib.Calibration.Calibrate(); calib.Run(); } else { // index++; SockClient.Single.Send("CalibOK"+indexs); ClassFustion.SaveText("发送信号:" + "CalibOK" + indexs); } } } } using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace visionPro项目练习 { //封装基本文件基本操作功能 public class ClassFustion { //定义一个全局变量 public static string path; //定义一个全局变量来接收形参 static string InputsPaths = ""; //定义一个全局变量来接收形参 public static System.Windows.Forms.TextBox texts = null; // 新增:持久化日志文件路径 private static string _persistedLogPath = ""; //定义一个方法,用来保存文本到文件和控件中 public static void SaveText(string value, string InputsPath = null, System.Windows.Forms.TextBox text = null) { // 正确处理InputsPath参数 if (!string.IsNullOrEmpty(InputsPath)) { InputsPaths = InputsPath; } // 更新TextBox引用 if (text != null) { texts = text; } // 安全调用Invoke方法(关键修复) if ( texts != null && texts.IsHandleCreated && !texts.IsDisposed) { texts.Invoke(new Action(() => { texts.AppendText(value + "\r\n"); })); } else { // 可选:记录警告或改用其他日志方式 Console.WriteLine($"日志文本控件不可用: {value}"); } // 原有文件日志记录代码保持不变... string yearTime = Application.StartupPath + &quot;//" + DateTime.Now.Year.ToString(); string MonthTime = yearTime + DateTime.Now.ToLongDateString() + &quot;//"; string DayTime = MonthTime + DateTime.Now.ToLongDateString() + &quot;//" + "日志" + &quot;//"; if (!Directory.Exists(yearTime))//判断文件夹是否存在,不存在则创建 { Directory.CreateDirectory(yearTime); } if (!Directory.Exists(MonthTime))//判断文件夹是否存在,不存在则创建 { Directory.CreateDirectory(MonthTime); } if (!Directory.Exists(DayTime))//判断文件夹是否存在,不存在则创建 { Directory.CreateDirectory(DayTime); } //写入文件 FileStream fs = new FileStream(DayTime + "/" + "日志.txt", FileMode.Append); //定义写入流对象 StreamWriter streamWriter = new StreamWriter(fs, Encoding.Default); //写入文件内容 streamWriter.WriteLine(value); //关闭流对象 streamWriter.Close(); //关闭文件流对象 fs.Close(); } // 新增:导出日志到指定文件 public static void ExportLog(string content, string filePath) { try { // 写入文件 File.WriteAllText(filePath, content, Encoding.UTF8); } catch (Exception ex) { MessageBox.Show($"日志导出失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // 新增:从文件加载日志 public static string LoadLog(string filePath) { try { // 读取文件 return File.ReadAllText(filePath, Encoding.UTF8); } catch (Exception ex) { MessageBox.Show($"日志加载失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return string.Empty; } } // 修改:保存时设置持久化路径 public static void PersistLogPath(string filePath) { // 设置持久化日志路径 _persistedLogPath = filePath; } // 修改:获取持久化日志路径 public static string GetPersistedLogPath() { return _persistedLogPath; } //这里定义一个方法,用来选择要保存文件的文件夹 //在Form1中,拖一个按钮,点击事件中调用该方法,就可以选择文件夹了 public static void FolderBrowserDialog() { using (FolderBrowserDialog fbd = new FolderBrowserDialog()) { fbd.Description = "请选择 要保存文件的文件夹"; if (fbd.ShowDialog() == DialogResult.OK) { path = fbd.SelectedPath;//查看返回路径 } } } //这里定义一个方法,用来打开文件,并且在Form1中,拖一个按钮,点击事件中 //调用该方法,就可以打开文件了,并且将文件中的日志显示在TextBox1中 public static void OpenText() { System.Diagnostics.Process.Start(path);//打开文件 } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Sockets; using System.Net; using System.Threading; using System.Windows.Forms; using static System.Collections.Specialized.BitVector32; using System.Web.Services.Description; namespace communication { /// <summary> /// 以太网客户端 /// </summary> /// public class SockClient { //定义一个委托 public delegate void Del(string vlue); public Del del; #region 单例模式 private static SockClient single = null; /// <summary> /// 通讯单例 /// </summary> /// public static SockClient Single { get { if (single == null) { single = new SockClient(); } return single; } } #endregion #region sock通讯 #region 变量 /// <summary> /// 客户端 /// </summary> Socket tcp; public string value = ""; #endregion /// <summary> /// 链接通讯 /// </summary> /// <param name="IP">ip地址</param> /// <param name="port">端口号</param> /// <param name="mothed">绑定方法</param> public void Connect(string IP, int port) { if (tcp == null || !tcp.IsBound) { try { //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议) tcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将IP地址和端口号绑定到网络节点point上,连接服务器 tcp.Connect(IPAddress.Parse(IP), port); //创建线程接收数据 Thread th = new Thread(th_); th.IsBackground = true; th.Start(); } catch (Exception) { MessageBox.Show("连接失败"); } } } /// <summary> /// 线程调用的方法,接收服务器消息 /// </summary> private void th_() { //创建一个内存缓冲区,其大小为1024*1024字节 即1M。 byte[] Byte = new byte[1024 * 1024]; while (true) { Thread.Sleep(5);//线程安全一定加延时 try {//接收到监听的Socket的数据 int num = tcp.Receive(Byte); if (num == 0)//当服务器断开,num收到的字节数为0,可作为退出机制 { tcp.Close();//退出自动关闭客户端 tcp.Dispose(); return; } //利用 Encoding.Default.GetString 获取客户端信息,注意是 字节 转化为 字符串 value = Encoding.Default.GetString(Byte, 0, num); del.Invoke(value); } catch (Exception ex) { MessageBox.Show("接收信号异常:" + ex.Message); } } } /// <summary> /// 发送数据至服务器 /// </summary> public void Send(string value) { try { tcp.Send(Encoding.Default.GetBytes(value)); } catch (Exception) { throw new Exception("发送信号异常"); } } /// <summary> /// 关闭通讯 /// </summary> public void Close() { tcp.Close(); tcp.Dispose(); tcp = null; GC.Collect(); } #endregion } //创建一个以太网服务器 public class SockServer { Socket server; Socket newLink; #region 创建服务器 public void CreateSever(string IP, int port) { //创建一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议) server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建一个IP地址和端口号,用于监听客户端的连接请求 IPEndPoint iPEnd = new IPEndPoint(IPAddress.Parse(IP), port); server.Bind(iPEnd);//绑定IP地址和端口号 server.Listen(10);//设置最大连接数 Thread list = new Thread(Accept);//创建一个线程,用于监听客户端的连接请求 list.IsBackground = true;//设置为后台线程 list.Start();//开始监听客户端的连接请求 //创建线程接收数据 Thread th = new Thread(th_); th.IsBackground = true;//设置为后台线程 th.Start();//开始接收数据 } //创建一个监听客户端连接方法 private ManualResetEvent newLinkReady = new ManualResetEvent(false); public void Accept() { while (true) { // 阻塞,直到有客户端连接 Socket clientSocket = server.Accept(); // 初始化 newLink newLink = clientSocket; // 通知接收数据的线程 newLink 已经准备好 newLinkReady.Set(); } } public void th_() { // 等待 newLink 准备好 newLinkReady.WaitOne(); // 创建一个内存缓冲区,其大小为1024*1024字节 即1M。 byte[] Byte = new byte[1024 * 1024]; while (true) // 循环接收客户端的消息 { Thread.Sleep(5); // 线程安全一定加延时 // 接收客户端的消息,并将其存入Byte数组中 int num = newLink.Receive(Byte); if (num == 0) // 当客户端断开,num收到的字节数为0,可作为退出机制 { newLink.Close(); // 退出自动关闭客户端 return; } } } //创建一个发送消息的方法 public void Send(string vlue) { //将字符串转化为字节,发送给客户端 newLink.Send(Encoding.Default.GetBytes(vlue)); //发送回车换行,便于客户端接收 newLink.Send(Encoding.Default.GetBytes("\r\n")); } //创建一个关闭服务器的方法 public void Close() { server.Close();//关闭服务器 server.Dispose();//释放资源 } #endregion } } 请帮我优化此程序,是优化程序不是大幅度修改程序,优化完之后,要能保证客户端要能和服务器上位机通讯的上,即能互相接收消息也能互相发消息,优化之后也要保证程序不会报错,要能保证日志显示在文本框上,并且给服务器上位机发消息要能接收到服务器上位机回馈的消息,就比如给上位机发送:触发标定信号 ccd--->对方:CalibOK0 对方--->ccd: Calib:0;X,Y# 然后服务器上位机回馈,比如发送:上相机 触发拍照信号 对方--->CCD :CameraS1:X,Y#R$ CCD--->对方 :CameraOK:X,Y#R$ ***********多点拍照************ 上相机 触发拍照信号 对方--->CCD :CameraS1:X,Y#R$ CCD--->对方 :Multipoint3 CCD--->对方 :CameraMultipoint#X1,Y1#X2,Y2...#XN,YN# ***********双相机************ 上相机 触发拍照信号 对方--->CCD :CameraS1:X,Y#R$ CCD--->对方 :CameraOKS 下相机 触发拍照信号 对方--->CCD :CameraS2:X,Y#R$ CCD--->对方 :CameraOK:X,Y#R$
最新发布
11-20
在住窗体里面代码如下CogAcqFifoTool Myacq = null; ICogImage Image = null; CogToolBlock tb = null; private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; ShowMsg("程序启动"); ShowMsg("开始加载相机"); ShowMsg("开始建立通信"); ShowMsg("开始加载Vpp"); LoadAcq(); if (Myacq != null) { ShowMsg("相机加载完毕"); } serialPort1.Open(); if (serialPort1.IsOpen) { ShowMsg("通信建立完成"); } tb = LoadTB.LoadTBFun(); if (tb!=null) { ShowMsg("Vpp加载完成"); } } #region 加载相机 public void LoadAcq() { string path = Directory.GetCurrentDirectory() +"\\VPPS\\Cam.vpp"; Myacq = CogSerializer.LoadObjectFromFile(path)as CogAcqFifoTool; } #endregion private void 编辑相机ToolStripMenuItem_Click(object sender, EventArgs e) { if (Myacq!=null) { FirCam firCam = new FirCam(Myacq); firCam.ShowDialog(); } else { MessageBox.Show("请连接相机"); } } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //暂存 byte[] bytes = new byte[serialPort1.BytesToRead]; //读取 serialPort1.Read(bytes, 0, bytes.Length); //转码 string str = Encoding.Default.GetString(bytes); str.Trim(); if (str.Contains("TT")) { ShowMsg("开始采图"); Myacq.Run(); cogRecordDisplay1.Fit(); cogRecordDisplay1.Image = Myacq.OutputImage; Image = Myacq.OutputImage; cogRecordDisplay1.Fit(); ShowMsg("采图完成"); ShowMsg("开始识别"); tb.Inputs["OutputImage"].Value = Image; tb.Run(); cogRecordDisplay2.Record = tb.CreateLastRunRecord().SubRecords[0]; cogRecordDisplay2.Fit(); if (tb.Outputs["Result1"].Value.ToString()==tb.Outputs["Result2"].Value.ToString()) { ShowMsg("检测结果为OK"); button1.BackColor = Color.Green; textBox1.Text = "OK"; } else { ShowMsg("检测结果为NG"); button1.BackColor = Color.Red; textBox1.Text = "NG"; } } }在我的记载类中代码如下 internal class LoadTB { public static CogToolBlock tb = null; public static CogToolBlock LoadTBFun() { string path = Directory.GetCurrentDirectory()+"\\VPPS\\TB.vpp"; tb = CogSerializer.LoadObjectFromFile(path) as CogToolBlock; return CogSerializer.LoadObjectFromFile(path) as CogToolBlock; }主窗体里面的tb是这个类的方法返回值,但是在我的cogRecordDisplay里面的record加载不出来,这是有什么原因造成的
09-14
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值