C#线程中操作界面&异步线程

mac2025-10-03  2

方法一

最简单的方法如下 线程中修改按钮btn_move的属性: btn_move.Invoke( new Action( ()=>{ btn_move.Enabled = true; } ) );

方法二

下面是一个线程中在界面richTextBox控件中显示信息的实例 方便理解 C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它。 此时它将会在内部调用new MethodInvoker(LoadGlobalImage)来完成下面的步骤。 这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了

**

注意:在委托函数内不要使用sleep();会阻塞线程

**

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; namespace 线程控制界面 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } delegate void testDelete(string str); void AddMsg(string str) { if (!this.richTextBox1.InvokeRequired)//判断不在线程中访问 { richTextBox1.Text = richTextBox1.Text + str+"\r\n"; // Thread.Sleep(200);//委托中一定不要有sleep,不然卡顿 // Application.DoEvents(); } else { testDelete mDelete = new testDelete(AddMsg);//实现委托 this.BeginInvoke(mDelete , new object[] { str } );//异步执行 // Thread.Sleep(500);//委托中不要有sleep,不然卡顿 // Application.DoEvents(); } } private void button2_Click(object sender, EventArgs e) { // chenge(); Task mm = new Task( () => { while (true) { chenge("123"); Thread.Sleep(100); Application.DoEvents(); } }); mm.Start(); } } }

方法三

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Timers; using System.Threading; using System.Windows.Forms; namespace 线程中窗体消息打印 { class Message { public enum EM_MSGTYPE { ERR = 0x01, WAR = 0x02, NOR = 0x04, DBG = 0x08, SYS = 0x10, SAVE_ERR = (ERR << 8), SAVE_WAR = (WAR << 8), SAVE_NOR = (NOR << 8), SAVE_DBG = (DBG << 8), SAVE_SYS = (SYS << 8) }; public struct MsgData { public EM_MSGTYPE msg_type; public DateTime dt; public string msg; public override string ToString() { return string.Format("[{0}] [{1:HH:mm:ss.fff}] {2}", msg_type.ToString(), dt, msg); } } FileStream Log; string str_date; private static readonly Object LockObj = new object(); LinkedList<MsgData> list_msgdat = new LinkedList<MsgData>(); object displayer; public EM_MSGTYPE MsgCfg = (EM_MSGTYPE)0xFFFF; public int MsgMaxLine = 200; System.Timers.Timer timer; #region 初始化 public Message(int MaxLine = 200, EM_MSGTYPE Cfg = (EM_MSGTYPE)0xFFFF) { MsgCfg = Cfg; MsgMaxLine = MaxLine; } ~Message() { if (Log != null) { Log.Close(); Log = null; } } public void StartUpdate(object displayer) { if (displayer == null) return; this.displayer = displayer; //显示刷新 if (timer == null) { timer = new System.Timers.Timer(200); timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); timer.AutoReset = true; timer.Enabled = true; } } public void ShowMsgCfg(int MaxLine, EM_MSGTYPE Cfg) { MsgCfg = Cfg; MsgMaxLine = MaxLine; } private void timer_Elapsed(object sender, ElapsedEventArgs e) { if (list_msgdat.Count == 0 || displayer == null) return; ShowMsgCallback(displayer); } #endregion #region 保存Message为log文档 public void SaveMsg(string MsgStr) { byte[] byData; if (Log == null || 0 != string.Compare(str_date, DateTime.Now.ToString("yyyy-MM-dd"))) { String str; str = Path.GetFullPath("..") + "\\log\\"; if (!Directory.Exists(str)) { //文件夹不存在则创建 Directory.CreateDirectory(str); } try { if (Log != null) { Log.Close(); Log = null; } str += DateTime.Now.ToString("yyyy-MM-dd") + ".log"; if (!File.Exists(str)) { Log = new FileStream(str, FileMode.Create); } else { Log = new FileStream(str, FileMode.Open); } str_date = DateTime.Now.ToString("yyyy-MM-dd"); } catch (Exception) { return; } } if (Log != null) { MsgStr = MsgStr + Environment.NewLine; Log.Seek(0, SeekOrigin.End); byData = System.Text.Encoding.Default.GetBytes(MsgStr); if (Log.CanWrite == true) Log.Write(byData, 0, byData.Length); } } #endregion #region 委托显示 delegate void DisplayCallback(object displayer); public void ShowMsgCallback(object displayer) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. int n = 0; Type type = displayer.GetType(); dynamic obj = Convert.ChangeType(displayer, type); while (obj.IsHandleCreated == false) { //解决窗体关闭时出现“访问已释放句柄“的异常 if (obj.Disposing || obj.IsDisposed) return; Application.DoEvents(); Thread.Sleep(1); if (n++ > 100) return; } //如果调用控件的线程和创建创建控件的线程不是同一个则为True if (obj.InvokeRequired) { DisplayCallback d = new DisplayCallback(ShowMsgCallback); obj.BeginInvoke(d, new object[] { displayer }); } else { showmsg(obj); } } #endregion #region 显示到指定控件 public void showmsg(TextBox tb) { if (list_msgdat.Count == 0 || tb == null) return; while (list_msgdat.Count > 0) { MsgData msg = list_msgdat.First(); if ((msg.msg_type & MsgCfg) != 0) { tb.AppendText(msg.ToString() + "\r\n"); } if (((int)msg.msg_type & ((int)MsgCfg) >> 8) != 0) { SaveMsg(msg.ToString()); } if (tb.Lines.Count() > MsgMaxLine / 2) { List<string> str_list = tb.Lines.ToList(); str_list.RemoveAt(0); tb.Lines = str_list.ToArray(); } tb.SelectionStart = tb.Text.Length; tb.ScrollToCaret(); lock (LockObj) { list_msgdat.RemoveFirst(); } } } /// <summary> /// 在RichTextBox中显示信息 /// </summary> /// <param name="rtb"></param> public void showmsg(RichTextBox rtb) { if (list_msgdat.Count == 0 || rtb == null) return; while (list_msgdat.Count > 0) { MsgData msg = list_msgdat.First(); if ((msg.msg_type & MsgCfg) != 0) { rtb.AppendText(msg.ToString() + "\r\n"); if (msg.msg_type == EM_MSGTYPE.DBG) rtb.SelectionColor = System.Drawing.Color.DarkGray; else if (msg.msg_type == EM_MSGTYPE.NOR) rtb.SelectionColor = System.Drawing.Color.Blue; else if (msg.msg_type == EM_MSGTYPE.WAR) rtb.SelectionColor = System.Drawing.Color.DarkOrange; else if (msg.msg_type == EM_MSGTYPE.ERR) rtb.SelectionColor = System.Drawing.Color.Red; } //if (((int)msg.msg_type & ((int)MsgCfg) >> 8) != 0) //{ // SaveMsg(msg.ToString()); //} if (rtb.Lines.Count() > MsgMaxLine / 2) rtb.Lines[0].Remove(0); rtb.SelectionStart = rtb.Text.Length; rtb.ScrollToCaret(); lock (LockObj) { list_msgdat.RemoveFirst(); } } } /// <summary> /// 在表格中显示信息 /// </summary> /// <param name="dgv"></param> public void showmsg(DataGridView dgv) { if (list_msgdat.Count == 0 || dgv == null) return; //bupdate = false; //create col if (dgv.ColumnCount < 3) { dgv.Columns.Clear(); dgv.Columns.Add("dt", "时间"); dgv.Columns.Add("type", "类型"); dgv.Columns.Add("disc", "内容"); dgv.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; dgv.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgv.Columns[2].FillWeight = 100; dgv.Columns[2].SortMode = DataGridViewColumnSortMode.NotSortable; dgv.ColumnHeadersHeight = 18; dgv.RowHeadersVisible = false; dgv.ReadOnly = true; dgv.AllowUserToAddRows = false; dgv.AllowUserToResizeColumns = false; dgv.AllowUserToResizeRows = false; dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dgv.ScrollBars = ScrollBars.Vertical; dgv.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(showtext); dgv.Rows.Clear(); } while (list_msgdat.Count > 0) { try { MsgData msg = list_msgdat.First(); if ((msg.msg_type & MsgCfg) != 0) { int idx = dgv.Rows.Add(); DataGridViewRow row = dgv.Rows[idx]; row.Cells[0].Value = msg.dt.ToString("HH:mm:ss.fff"); row.Cells[1].Value = msg.msg_type.ToString(); row.Cells[2].Value = msg.msg; if (msg.msg_type == EM_MSGTYPE.DBG) row.DefaultCellStyle.BackColor = dgv.BackgroundColor; else if (msg.msg_type == EM_MSGTYPE.NOR) row.DefaultCellStyle.BackColor = System.Drawing.Color.LightCyan; else if (msg.msg_type == EM_MSGTYPE.WAR) row.DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; else if (msg.msg_type == EM_MSGTYPE.ERR) row.DefaultCellStyle.BackColor = System.Drawing.Color.Pink; else if (msg.msg_type == EM_MSGTYPE.SYS) row.DefaultCellStyle.BackColor = dgv.BackgroundColor; dgv.FirstDisplayedScrollingRowIndex = idx; if (dgv.RowCount > MsgMaxLine) dgv.Rows.RemoveAt(0); } if (((int)msg.msg_type & ((int)MsgCfg) >> 8) != 0) { SaveMsg(msg.ToString()); } //if (list_msgdat.Count % 10 == 0) //{ // Application.DoEvents(); // Thread.Sleep(1); //} } catch (Exception ex) { } lock (LockObj) { list_msgdat.RemoveFirst(); } } } void showtext(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0 || e.ColumnIndex < 0) return; MessageBox.Show(((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString()); } #endregion #region 添加显示信息到缓存 public void AddMsg(EM_MSGTYPE MsgType, string MsgStr) { if (MsgStr.Length == 0) return; try { MsgData msg = new MsgData(); msg.msg_type = MsgType; msg.msg = MsgStr; msg.dt = DateTime.Now; lock (LockObj) { list_msgdat.AddLast(msg); if (list_msgdat.Count > MsgMaxLine) list_msgdat.RemoveFirst(); } } finally { //pLockMsg.ReleaseMutex(); } } public void AddMsg(string str) { AddMsg(EM_MSGTYPE.NOR, str); } #endregion } }

应用如下:

namespace 线程中窗体消息打印 { public partial class Form1 : Form { Message msg = new Message(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { msg.StartUpdate(richTextBox1); } private void button1_Click(object sender, EventArgs e) { msg.AddMsg("123344"); } } }
最新回复(0)