C#.网络编程 Socket基础(六)WPF工程 UI界面卡顿问题及其解决办法、UI界面没有卡顿,第二次实例化导致UI界面不能更新界面问题及其解决办法

简介:

本文将介绍简单、复杂的卡顿问题(本文的复杂卡顿问题,表现在UI不能更新)。

一、简单卡顿问题及其解决方法,请参考我的另一篇博文

 C#.网络编程 Socket基础(四) WPF系统Socket TCP协议 服务器与客户端 不同类型文件传输,解决UI线程(异步委托)与工作线程的卡顿问题

设计思路  主线程——>实例化——>次线程——>在次线程中,直接用实例更新到主线线程的UI  如图所示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Threading;
using KeenRayLargePC.Views;
using KeenRayLargePC.PublicFunc;

namespace KeenRayLargePC
{
    public partial class MainWindow : Window 
    {
        //传递页面类型
        string strPageType = null;

        //启动页面标志
        static byte[] byt_StudyPage_RecFlag = new byte[2] { 0x00, 0 };
        static byte[] byt_ReviewPage_RecFlag = new byte[2] { 0x01, 0 };
        static byte[] byt_HistoryPage_RecFlag = new byte[2] { 0x02, 0 };
        //启动图片接收、字符接收标志
        static byte[] byt_String_RecFlag = new byte[2] { 0x00, 0 };
        static byte[] byt_Image_RecFlag = new byte[2] { 0x04, 0 };
        //启动用户、列表、曝光标志
        static byte[] byt_User_RecFlag = new byte[2] { 0x00, 0 };//这里出现的0x00标志与前面的0x00没有联系。
        static byte[] byt_ListView_RecFlag = new byte[2] { 0x08, 0 };
        static byte[] byt_Expose_RecFlag = new byte[2] { 0x10, 0 };
        //启动KV、mA、ms、mAs标志
        static byte[] byt_ExposeKV_RecFlag = new byte[2] { 0x00, 0 };
        static byte[] byt_ExposemA_RecFlag = new byte[2] { 0x20, 0 };
        static byte[] byt_Exposems_RecFlag = new byte[2] { 0x40, 0 };
        static byte[] byt_ExposemAs_RecFlag = new byte[2] { 0x60, 0 };
        //启动 Plus/Reduce标志
        static byte[] byt_ExposePlus_RecFlag = new byte[2] { 0x00, 0 };
        static byte[] byt_ExposeReduce_RecFlag = new byte[2] { 0x80, 0 };


        Int16 Int16_StudyPage_RecFlag = System.BitConverter.ToInt16(byt_StudyPage_RecFlag, 0);
        Int16 Int16_ReviewPage_RecFlag = System.BitConverter.ToInt16(byt_ReviewPage_RecFlag, 0);
        Int16 Int16_HistoryPage_RecFlag = System.BitConverter.ToInt16(byt_HistoryPage_RecFlag, 0);
        Int16 Int16_String_RecFlag = System.BitConverter.ToInt16(byt_String_RecFlag, 0);
        Int16 Int16_Image_RecFlag = System.BitConverter.ToInt16(byt_Image_RecFlag, 0);
        Int16 Int16_User_RecFlag = System.BitConverter.ToInt16(byt_User_RecFlag, 0);
        Int16 Int16_ListView_RecFlag = System.BitConverter.ToInt16(byt_ListView_RecFlag, 0);
        Int16 Int16_Expose_RecFlag = System.BitConverter.ToInt16(byt_Expose_RecFlag, 0);
        Int16 Int16_ExposeKV_RecFlag = System.BitConverter.ToInt16(byt_ExposeKV_RecFlag, 0);
        Int16 Int16_ExposemA_RecFlag = System.BitConverter.ToInt16(byt_ExposemA_RecFlag, 0);
        Int16 Int16_Exposems_RecFlag = System.BitConverter.ToInt16(byt_Exposems_RecFlag, 0);
        Int16 Int16_ExposemAs_RecFlag = System.BitConverter.ToInt16(byt_ExposemAs_RecFlag, 0);
        Int16 Int16_ExposePlus_RecFlag = System.BitConverter.ToInt16(byt_ExposePlus_RecFlag, 0);
        Int16 Int16_ExposeReduce_RecFlag = System.BitConverter.ToInt16(byt_ExposeReduce_RecFlag, 0);

        Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        StudyPage studyPage = new StudyPage();
        ReviewPage reviewPage = new ReviewPage();
        HistoryPage historyPage = new HistoryPage();
        ExposeValueMsgFunc exposeValueMsgFunc = new ExposeValueMsgFunc();
        ImageFunc imageFunc = new ImageFunc();
        ListViewMsgFunc listViewMsgFunc = new ListViewMsgFunc();
        UserMsgFunc userMsgFunc = new UserMsgFunc();

        public MainWindow()
        {
            InitializeComponent();

            IPAddress serverIP = IPAddress.Parse("127.0.0.1");
            IPEndPoint serverIPEndPoint = new IPEndPoint(serverIP, 50000);
            //获得要连接的远程服务器应用程序的IP地址和端口号
            Client.Connect(serverIPEndPoint);

            int i1 = Thread.CurrentThread.ManagedThreadId;
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId);
            //ShowMsg(Thread.CurrentThread.ManagedThreadId);
            //MessageBox.Show("连接成功1");
            //开启一个新的线程不停地接收服务器端发来的消息
            Thread threadReceive = new Thread(Receive);
            //将threadReceive设置为后台线程
            threadReceive.IsBackground = true;
            //启动线程
            threadReceive.Start();
        }

        void Receive()
        {
            int i2 = Thread.CurrentThread.ManagedThreadId;
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    //实际接收到的有效字节数
                    int r = 0;
                    r = Client.Receive(buffer);
                    if (r == 0)//未收到任何东西
                    {
                        MessageBox.Show("中止1");
                        break;
                    }
                    else//有收到信息
                    {
                        int i3 = Thread.CurrentThread.ManagedThreadId;
                        //拷贝,找出butter的标志位。
                        byte[] byt_RecFlag = new byte[2];
                        Array.ConstrainedCopy(buffer, 0, byt_RecFlag, 0, byt_RecFlag.Length);
             
                        //转成整数,以便进行与操作。
                        Int16 Int16_byt_RecFlag = System.BitConverter.ToInt16(byt_RecFlag, 0);
                        //Int16_byt_RecFlag & 0x03,表示提取字节的前两位。
                        if ((Int16_byt_RecFlag & 0x03) == Int16_StudyPage_RecFlag)//前两位为0,则启动StudyPage。
                        {
                            int i4 = Thread.CurrentThread.ManagedThreadId;

                            strPageType = "studyPage";
                            App.Current.Dispatcher.Invoke((Action)delegate ()
                            {
                                int i5 = Thread.CurrentThread.ManagedThreadId;
                                Frame.Content = studyPage;
                            });
                            //Int16_byt_RecFlag & 0x04,表示提取字节的第三位。
                            if ((Int16_byt_RecFlag & 0x04) == Int16_String_RecFlag)//启动文字信息。
                            {
                                if ((Int16_byt_RecFlag & 0x11) == Int16_User_RecFlag)//启动用户信息
                                {
                                    //this.Dispatcher.BeginInvoke((Action)delegate ()//次线程threadReceive调用了主线程 App.Current.
                                    //userMsgFunc.GetUserMsgFunc(r, buffer, strPageType);
                                    //App.Current.Dispatcher.BeginInvoke((Action)delegate ()
                                    //{
                                    //    int i6 = Thread.CurrentThread.ManagedThreadId;//主线程
                                    userMsgFunc.GetUserMsgFunc(r, buffer, studyPage);
                                    //});
                                    //标志位占两个字节
                                    //int iFlagByteLong = 2;

                                    字符信息的长度占一个字节
                                    //int iMsgByteLong = 1;

                                    病人信息的字节长度
                                    //int iPatientNumByteLong = 10;
                                    //int PatientNameByteLong = 12;
                                    //int iPatientSexByteLong = 3;
                                    //int iPatientAgeByteLong = 3;
                                    //int iPatientBodyByteLong = 6;

                                    用户信息
                                    //byte[] byt_PatientNum = new byte[iPatientNumByteLong];
                                    //byte[] byt_PatientnName = new byte[PatientNameByteLong];
                                    //byte[] byt_PatientSex = new byte[iPatientSexByteLong];
                                    //byte[] byt_PatientAge = new byte[iPatientAgeByteLong];
                                    //byte[] byt_PatientBody = new byte[iPatientBodyByteLong];
                                    //string str_PatientNum = null;
                                    //string str_PatientnName = null;
                                    //string str_PatientSex = null;
                                    //string str_PatientAge = null;
                                    //string str_PatientBody = null;
                                    将byt_bufferVar的用户内容按固定字节拷贝出来
                                    //Array.ConstrainedCopy(buffer, (iFlagByteLong + iMsgByteLong), byt_PatientNum, 0, iPatientNumByteLong);//byt_bufferVar的第四个字节(包含第四个字节)之后才是字符内容。
                                    //Array.ConstrainedCopy(buffer, (iFlagByteLong + iMsgByteLong + iPatientNumByteLong), byt_PatientnName, 0, PatientNameByteLong);
                                    //Array.ConstrainedCopy(buffer, (iFlagByteLong + iMsgByteLong + iPatientNumByteLong + PatientNameByteLong), byt_PatientSex, 0, iPatientSexByteLong);
                                    //Array.ConstrainedCopy(buffer, (iFlagByteLong + iMsgByteLong + iPatientNumByteLong + PatientNameByteLong + iPatientSexByteLong), byt_PatientAge, 0, iPatientAgeByteLong);
                                    //Array.ConstrainedCopy(buffer, (iFlagByteLong + iMsgByteLong + iPatientNumByteLong + PatientNameByteLong + iPatientSexByteLong + iPatientAgeByteLong), byt_PatientBody, 0, iPatientBodyByteLong);

                                    包含了\0的字符串
                                    //str_PatientNum = System.Text.Encoding.UTF8.GetString(byt_PatientNum);
                                    //str_PatientnName = System.Text.Encoding.UTF8.GetString(byt_PatientnName);
                                    //str_PatientSex = System.Text.Encoding.UTF8.GetString(byt_PatientSex);
                                    //str_PatientAge = System.Text.Encoding.UTF8.GetString(byt_PatientAge);
                                    //str_PatientBody = System.Text.Encoding.UTF8.GetString(byt_PatientBody);

                                    去掉\0的字符串
                                    //str_PatientNum = str_PatientNum.Replace("\0", "");
                                    //str_PatientnName = str_PatientnName.Replace("\0", "");
                                    //str_PatientSex = str_PatientSex.Replace("\0", "");
                                    //str_PatientAge = str_PatientAge.Replace("\0", "");
                                    //str_PatientBody = str_PatientBody.Replace("\0", "");

                                    将用户字符串信息,更新到UI。
                                    //App.Current.Dispatcher.BeginInvoke((Action)delegate ()//MainWindow ID
                                    //{
                                    //    int i8 = Thread.CurrentThread.ManagedThreadId;

                                    //    if (strPageType == "studyPage")
                                    //    {
                                    //        int i9 = Thread.CurrentThread.ManagedThreadId;
                                    //        //StudyPage studyPage = new StudyPage();
                                    //        studyPage.lbl_PatientNum_Study.Content = str_PatientNum;
                                    //        studyPage.lbl_PatientnName_Study.Content = str_PatientnName;
                                    //        studyPage.lbl_PatientSex_Study.Content = str_PatientSex;
                                    //        studyPage.lbl_PatientAge_Study.Content = str_PatientAge;
                                    //        studyPage.lbl_PatientBody_Study.Content = str_PatientBody;
                                    //    }
                                    //    else if (strPageType == "reviewPage")
                                    //    {
                                    //        //ReviewPage reviewPage = new ReviewPage();
                                    //        reviewPage.lbl_PatientNum_Review.Content = str_PatientNum;
                                    //        reviewPage.lbl_PatientnName_Review.Content = str_PatientnName;
                                    //        reviewPage.lbl_PatientSex_Review.Content = str_PatientSex;
                                    //        reviewPage.lbl_PatientAge_Review.Content = str_PatientAge;
                                    //        reviewPage.lbl_PatientBody_Review.Content = str_PatientBody;
                                    //    }
                                    //});


                                }
                                else if ((Int16_byt_RecFlag & 0x11) == Int16_ListView_RecFlag)//启动列表信息
                                {
                                    listViewMsgFunc.GetListViewMsgFunc(r, buffer, strPageType);
                                }
                                else if ((Int16_byt_RecFlag & 0x11) == Int16_Expose_RecFlag)//启动曝光信息
                                {
                                    if ((Int16_byt_RecFlag & 0x60) == Int16_ExposeKV_RecFlag)//启动KV
                                    {
                                        if ((Int16_byt_RecFlag & 0x80) == Int16_ExposePlus_RecFlag)//加
                                        {
                                            string strVar = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_KVValue.Content = strVar;
                                            });
                                        }
                                        else if ((Int16_byt_RecFlag & 0x80) == Int16_ExposeReduce_RecFlag)//减
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_KVValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });

                                        }
                                    }
                                    else if ((Int16_byt_RecFlag & 0x60) == Int16_ExposemA_RecFlag)//启动mA
                                    {
                                        if ((Int16_byt_RecFlag & 0x80) == Int16_ExposePlus_RecFlag)//加
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_mAValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                        else if ((Int16_byt_RecFlag & 0x80) == Int16_ExposeReduce_RecFlag)//减
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_mAValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                    }
                                    else if ((Int16_byt_RecFlag & 0x60) == Int16_Exposems_RecFlag)//启动ms
                                    {
                                        if ((Int16_byt_RecFlag & 0x80) == Int16_ExposePlus_RecFlag)//加
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_msValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                        else if ((Int16_byt_RecFlag & 0x80) == Int16_ExposeReduce_RecFlag)//减
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_msValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                    }
                                    else if ((Int16_byt_RecFlag & 0x60) == Int16_ExposemAs_RecFlag)//启动mAs
                                    {
                                        if ((Int16_byt_RecFlag & 0x80) == Int16_ExposePlus_RecFlag)//加
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_mAsValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                        else if ((Int16_byt_RecFlag & 0x80) == Int16_ExposeReduce_RecFlag)//减
                                        {
                                            App.Current.Dispatcher.Invoke((Action)delegate ()
                                            {
                                                studyPage.lbl_mAsValue.Content = exposeValueMsgFunc.GetExposeValueMsgFunc(r, buffer);
                                            });
                                        }
                                    }

                                }
                            }
                            else if ((Int16_byt_RecFlag & 0x04) == Int16_Image_RecFlag)//启动图片信息
                            {
                                App.Current.Dispatcher.Invoke((Action)delegate ()
                                {
                                    imageFunc.GetImageFunc(r, buffer, strPageType);
                                });
                            }
                        }
                        else if ((Int16_byt_RecFlag & 0x03) == Int16_ReviewPage_RecFlag)//前两位为1,则启动ReviewPage
                        {
                            strPageType = "reviewPage";
                            App.Current.Dispatcher.Invoke((Action)delegate ()
                            {
                               
                                Frame.Content = reviewPage;
                            });
                            //Frame.Content = reviewPage;
                            //Int16_byt_RecFlag & 0x04,表示提取字节的第三位。
                            if ((Int16_byt_RecFlag & 0x04) == Int16_String_RecFlag)//启动文字-用户信息。
                            {
                                userMsgFunc.GetUserMsgFunc(r, buffer, studyPage);
                                //App.Current.Dispatcher.Invoke((Action)delegate ()
                                //{
                                //    //Frame.Content = reviewPage;
                                //    userMsgFunc.GetUserMsgFunc(r, buffer, strPageType);
                                //});
                            }
                            else if ((Int16_byt_RecFlag & 0x04) == Int16_Image_RecFlag)//启动图片信息
                            {
                                imageFunc.GetImageFunc(r, buffer, strPageType);
                            }
                        }
                        else if ((Int16_byt_RecFlag & 0x03) == Int16_HistoryPage_RecFlag)//前两位为2,则启动HistoryPage
                        {
                            strPageType = "HistoryPage";
                            App.Current.Dispatcher.Invoke((Action)delegate ()
                            {
                                Frame.Content = historyPage;
                            });

                            //Int16_byt_RecFlag & 0x04,表示提取字节的第三位。
                            if ((Int16_byt_RecFlag & 0x04) == Int16_String_RecFlag)//启动文字信息。
                            {
                                if ((Int16_byt_RecFlag & 0x11) == Int16_ListView_RecFlag)//启动列表信息
                                {
                                    listViewMsgFunc.GetListViewMsgFunc(r, buffer, strPageType);
                                }
                            }
                        }
                    }
                }
                catch
                {
                    int iShowMessageBoxCount = 0;
                    while (iShowMessageBoxCount < 1)
                    {
                        MessageBox.Show("连接不上");
                        iShowMessageBoxCount++;
                    }
                    //MessageBox.Show("重新启动连接");
                    //MessageBox.Show("连接不上");
                    //break;

                }

                
            }
        }

        void ShowMsg(string str)
        {
            studyPage.txtLog.AppendText(str + "\r\n");
        }

        private void BtnSysShutDown_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }


    }
}

二、复杂的卡顿问题 

2.1、复杂卡顿问题的入门介绍

关于Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析,这里有一篇典型的博客:

https://blog.csdn.net/yl2isoft/article/details/11711833

2.2、  App.Current.Dispatcher.Invoke 和  this.Dispatcher.BeginInvoke的区别

两者都是指当前的窗口

2.3、我所遇到的复杂卡顿问题及其解决办法(恍然大悟)。

问题:

        在我的WPF工程里面,Sokcets介绍一切正常,数据介绍没有问题,单步执行没有没有,而且采用了之前的简单卡顿的解决方案来设计程序。次线性接收信息,经过一番处理后,但就是没办法更新到主线程MainWindow中:

       原来,问题出现在一番处理的过程中。我的设计思路  是设计思路  主线程——>studyPage实例化——>次线程——>studyPage实例化——>在次线程中,直接用实例更新到主线线程的UI  如图所示。

       第二个studyPage实例化,我是放到另外一个类中:

非常糟糕的是,多了这一步实例化,让我陷入了万劫不复的地步。其导致UI不能更新。

     为了分析其根本原因,我现在把第一次实例化studyPage的数据拿出来:


 

第二次实例化后的数据:

看到了没有,这个一个局部变量,当类UserMsgFunc消亡后,类内的实例化studyPage也跟着消亡。所以第二个实例化的数据studyPage,与第一个studyPage的数据根本没有半毛钱关系。第一个studyPage的数据还是保持原样,至始至终,第二次的实例化数据从来没有更新到主线程MianWindow的UI上。

       以上问题,属于把数据传到父类的问题。关于把数据传递父类的方法,有几种方法:

方法1:

    将第一个studyPage,作为一个参数,传递给类UserMsgFunc即可。即始终保持建立一个实例化的原则。

方法2:设置静态类static即可

具体参考 C# 基础(六)C# WPF中全面理解 全局变量、局部变量的区别与实现

方法3:回调函数

方法4:委托。

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值