方法一
最简单的方法如下 线程中修改按钮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";
}
else
{
testDelete mDelete
= new testDelete(AddMsg
);
this.BeginInvoke(mDelete
, new object[] { str
} );
}
}
private void button2_Click(object sender
, EventArgs e
)
{
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
)
{
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;
}
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();
}
}
}
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 (rtb
.Lines
.Count() > MsgMaxLine
/ 2) rtb
.Lines
[0].Remove(0);
rtb
.SelectionStart
= rtb
.Text
.Length
;
rtb
.ScrollToCaret();
lock (LockObj
)
{
list_msgdat
.RemoveFirst();
}
}
}
public void showmsg(DataGridView dgv
)
{
if (list_msgdat
.Count
== 0 || dgv
== null) return;
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());
}
}
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
{
}
}
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");
}
}
}