有时候我们需要在线程中打印消息到界面,但界面线程和运行线程之间不能跨线程操作,会报错误,解决方法如下,
1调用界面控件之前,检测当前线程是否和界面线程相同,
2如果不同,启用BeginInvoke委托调用方法解决异常
#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();
}
}
}