方法一
最简单的方法如下
线程中修改按钮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");
}
}
}