美文网首页
关于c# 主线程子线程用法规范, 以及子线程更新ui那些事和安

关于c# 主线程子线程用法规范, 以及子线程更新ui那些事和安

作者: 吉凶以情迁 | 来源:发表于2022-06-09 15:09 被阅读0次

    最近同事的一系列操作,惊掉了我的下巴,和那时候的我很像,我那时候玩易语言也不知道耗时操作应该怎么优化体验,应该怎么写,什么才是规范,
    直到遇到安卓,安卓强制不让在主线程写耗时代码,我才慢慢的进入了规范。
    安卓要想在子线程更新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

    相关文章

      网友评论

          本文标题:关于c# 主线程子线程用法规范, 以及子线程更新ui那些事和安

          本文链接:https://www.haomeiwen.com/subject/kysmmrtx.html