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

方法一

最简单的方法如下
线程中修改按钮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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值