最近同事的一系列操作,惊掉了我的下巴,和那时候的我很像,我那时候玩易语言也不知道耗时操作应该怎么优化体验,应该怎么写,什么才是规范,
直到遇到安卓,安卓强制不让在主线程写耗时代码,我才慢慢的进入了规范。
安卓要想在子线程更新ui,就需要对Looper进行操作,但是这都是强制写法,实际上肯定不是这么用的,子线程就不应该这么用。。
安卓比较偷懒的写法:
任意ui控件.post();传递函数进去就实现函数体主线程执行
实际上c#也是类似
任意ui控件.Invoke(代理方法,参数)
,在安卓可以通过Thread.currentThread.Name()
打印线程名,
在c#一样可以,但是默认为空,需要进行修改赋值才行。。
判断是否当前函数体代码在子线程运行的2种方法:
if (this.textBox_log.InvokeRequired)//若是调用控件的线程和建立建立控件的线程不是同一个则为True
{
//if (Thread.CurrentThread.Name.Equals("子线程"))//这句话和上面等同this.textBox_log.InvokeRequire
最后附属c#代码,改代码实现了 追加文本,不追加文本,
支持任意文本,标签控件改内容。也演示了如何判断是否在子线程的两种方法
完整代码
/// <summary>
///
/// </summary>
/// <param name="text">设置的内容</param>
/// <param name="append">是否追加只有当第三个参数控件 不为空才有效果 </param>
/// <param name="control"> 传递为空则修改textbox和label控件 textbox为追加 ,label为不追加</param>
private void SetText(string text, bool? append = false, Control? control = null)
{
Debug.WriteLine(Thread.CurrentThread.Name + ":" + text + ",isappend:" + append);
// 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.
if (this.textBox_log.InvokeRequired)//若是调用控件的线程和建立建立控件的线程不是同一个则为True
{
//if (Thread.CurrentThread.Name.Equals("子线程"))//这句话和上面等同this.textBox_log.InvokeRequire
while (!this.textBox_log.IsHandleCreated)
{
//解决窗体关闭时出现“访问已释放句柄“的异常
if (this.textBox_log.Disposing || this.textBox_log.IsDisposed)
return;
}
SetTextCallback callBack = new SetTextCallback(SetText);
if (control != null)//如果不为空则代表修改指定控件
{//这句话执行后还是调用当前方法,但是是在主线程运行的。 也就是走的else逻辑 ,
this.label_status.Invoke(callBack, new object[] { text, append, control });
}
else
{//如果没有传递control,则标签控件 为直接设置值,textbox控件则 追加值, 另外 ,这里的callback,
//不一定需要传递SetText,这里是偷懒复用当前方法参数,可以换成另外起一个主线程方法函数 也一样可以。
this.label_status.Invoke(callBack, new object[] { text, false, label_status });
this.textBox_log.Invoke(callBack, new object[] { text, true, textBox_log });
}
}
else
{//走主线程
if (control != null)
{
if (control is TextBox)
{
TextBox textBox = (control as TextBox);
if (append ?? false)
{
textBox.AppendText(text);
}
else
{
textBox.Text = text;
}
}
else
{
Label label = (control as Label);
if (append ?? false)
{
label.Text = label.Text + "\r\n" + text;
}
else
{
label.Text = text;
}
}
}
else
{
this.textBox_log.Text = "[主线程调用]" + text;
}
}
}
// 第一步:定义委托类型
// 将text更新的界面控件的委托类型
delegate void SetTextCallback(string text, bool? append, Control? control);
private void buttonreadresult_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "主线程";
SetText("开始查询", false, label_status);
if (loopRead)
{
SetText("当前已在运行,所以进行停止操作,当前已发送停止信号", false, label_status);
loopRead = false;
//MessageBox.Show("已停止");
return;
}
else
{
loopRead = true;
}
int count = 30;
int i = 0;
new Thread(() =>
{
Thread.CurrentThread.Name = "子线程";
SetText("[线程开始]", false, label_status);
SetText("[线程开始]\n", false, textBox_log);
while (loopRead)
{
try
{
//这是业务代码,需要循环读取dll 方法。
ReadResult(ref pStatus, pSN1, pSN2, pIMEI1, pIMEI2, pIMEI3, pIMEI4, pMEID, pBT, pWIFI, pMBSN, pCURef, pAPSWVer, pSWVer, pNFC, pCCID, pMsgLine, pMSG, pGrid, pFailKind, ref pErrs);
Thread.Sleep(1000);
System.Diagnostics.Debug.WriteLine("ppStatus=>" + pCURef);
System.Diagnostics.Debug.WriteLine("pMsgLine=>" + pMsgLine.ToString());
System.Diagnostics.Debug.WriteLine("pMSG=>" + pMSG);
System.Diagnostics.Debug.WriteLine("pErrs=>" + pErrs);
SetText("\r\n状态" + pCURef + "\r\nMsgLine:" + pMsgLine + "\r\nMSG" + pMSG + "\r\nerr" + pErrs+ "\r\n", true,textBox_log);
i++;
}
catch (Exception e)
{
SetText("执行出现异常:"+e.ToString());
Console.WriteLine("ERROR " + e.ToString());
loopRead = false;
break;
}
}
System.Diagnostics.Debug.WriteLine("[线程结束]已退出查询");
SetText("[线程结束]已退出查询",false,label_status);
}).Start();
}
参考
http://t.zoukankan.com/xingchen-p-2035083.html
http://www.javashuo.com/article/p-fqopwglf-hx.html
网友评论