m0_47661337 2021-12-03 23:46 采纳率: 100%
浏览 117
已结题

c#中如何在Timer控件中使用多线程处理加快数据处理速度

这个GetCount和Process是我自己写的方法,基本原理用来读取一个到达时间数组time,这个数组每秒更新一次,计算后更新灰度值数组,画出对应灰度图。但发现time的Intever设置1s时候一处理数据UI就会卡顿,在网上查应该在UI主线程外另加个新线程,那在这里就是开个新线程跑这两个自己写的数据处理方法?具体还需不需要考虑线程同步之类的问题,怎么改改才好呢

private void DataAna_Click(object sender, EventArgs e)
        {
            try
            {
                if (DataAna.Text == "Image")
                {
                    pixel.Initialize();
                    greyValue.Initialize();
                    greyValue = new int[32, 32];
                    String s = Interaction.InputBox("请输入成像时间", " ", "单位s", -1, -1);
                    if (!String.IsNullOrEmpty(s))
                    {
                        time = Convert.ToInt16(s);
                    }
                  //  this.result.Text = s;
                    DataAna.Text = "Stop";
                    timer2.Start();
                  
                }
                else if (DataAna.Text == "Stop")
                {
                    DataAna.Text = "Image";
                    timer2.Stop();
                    Process();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
private void timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                if (ttInterface != null && ttInterface.IsOpen())
                {
                    if (time != 0)
                    {
                        time--;
                    }
                    GetCount();
                    Process();
                    if (time == 0)
                    {
                        DataAna.Text = "Image";
                        timer2.Stop();
                       
                        MessageBox.Show("灰度图像已完成");
                    }
                }
            }
            catch (Exception ex)
            {
                richTextBox1.AppendText(ex.Message + "\n");
            }
        }
List<TempChannel> channelLst = new List<TempChannel>();

        private void GetCount()
        {
            channelLst.Clear();
            byte[] channels;
             //time数组就是要读取的数组,长度1000左右,每1s更新一次
            long[] times;
            // 把计数差小于某个值的两个通道看作是一个像元的响应
            for (int i = 0; i < 100; i++)
            {
                for (int j = i + 1; j < 100; j++)
                {
                    if (Math.Abs(times[i] - times[j]) < 10000  )
                    {
                        int min = Math.Min(channels[j], channels[i]);
                        int max = Math.Max(channels[i], channels[j]);
                        if (max > 32 && min < 33)
                        {
                   //chanel保存像元响应的行列位置
                            TempChannel channel = new TempChannel();
                            channel.channeli = min;
                            channel.channelj = max;
                            channelLst.Add(channel);
                        }
                    }
                }
            }
              //像素单元序号
            foreach (var item in channelLst)
            {
                pixel[item.channeli-1, item.channelj - 33]++;
            }
        }

        private void Process()
        { 
            pictureBox1.Image.Dispose();
            pictureBox1.Image = null;
            richTextBox2.Clear();
            int max = 0;
            int min = 100000;
            foreach (var num in pixel)
            {
                if (num > max)
                {
                    max = num;
                }
                if (num < min)
                {
                    min = num;
                }
            }
            for (int i = 0; i <= 31; i++)
            { 
                for (int j = 0; j <= 31 ;j++)
                {
                        if (pixel[i,j] != 0)
                        {
                            int num = i * 32 + j + 1;
                            richTextBox2.AppendText("第" + i+1 + "行  第" +j+1 +"列像元的计数为" + pixel[i,j]+"     ");

                        }
                    double index = 1000*(pixel[i, j] - min) / (max - min);
                        greyValue[i,j] = 255 -(int) index * 255/1000;
            
            ////显示
            Bitmap bmp = new Bitmap(32, 32);
            for (int i = 0; i < 32; i++)
            {
                for (int j = 0; j < 32; j++)
                {
                    int col = greyValue[j,i];
                    Color pix = Color.FromArgb(col,col,col);
                    bmp.SetPixel(i, j, pix);
                }
            }
            Bitmap bitmapOld = pictureBox1.Image as Bitmap;
            pictureBox1.Image = bmp;
            pictureBox1.Visible = true;
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            if (bitmapOld != null)
            {
                bitmapOld.Dispose();
            }
        }
  • 写回答

1条回答 默认 最新

  • CSDN专家-showbo 2021-12-04 10:00
    关注

    Timer执行的代码和UI同一个线程,如果长时间执行UI会假死。而用Thread和UI线程分开的,所以执行长时间任务不会导致UI假死,但是要访问UI中控件需要用代理,直接访问会报错,Timer则可以直接访问UI中控件。
    所以不想UI假死,直接启动个线程,不要用Timer。主要是改动访问UI控件时,判断从其他线程中访问需要用代理,下面这种结构

     if (this.InvokeRequired)
                    this.Invoke(new Action(() => {
    //访问UI控件的代码
    
                }));
    
    

    大概下面这种结构。

         System.Threading.Thread thread;
            private void DataAna_Click(object sender, EventArgs e)
            {
                try
                {
                    if (DataAna.Text == "Image")
                    {
                        pixel.Initialize();
                        greyValue.Initialize();
                        greyValue = new int[32, 32];
                        String s = Interaction.InputBox("请输入成像时间", " ", "单位s", -1, -1);
                        if (!String.IsNullOrEmpty(s))
                        {
                            time = Convert.ToInt16(s);
                        }
                        //  this.result.Text = s;
                        DataAna.Text = "Stop";
                        // timer2.Start();
                        thread = new System.Threading.Thread(()=> {
                            try
                            {
                                if (ttInterface != null && ttInterface.IsOpen())
                                {
                                    if (time != 0)
                                    {
                                        time--;
                                    }
                                    GetCount();
                                    Process();
                                    if (time == 0)
                                    {
                                        this.Invoke(new Action(()=> {
                                            DataAna.Text = "Image";
                                            //timer2.Stop();
                                            MessageBox.Show("灰度图像已完成");
    
                                        }));
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                richTextBox1.AppendText(ex.Message + "\n");
                            }
                        });
                        thread.Start();
                    }
                    else if (DataAna.Text == "Stop")
                    {
                        DataAna.Text = "Image";
                        // timer2.Stop();
                        thread.Abort();
                        Process();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            private void timer2_Tick(object sender, EventArgs e)
            {
                try
                {
                    if (ttInterface != null && ttInterface.IsOpen())
                    {
                        if (time != 0)
                        {
                            time--;
                        }
                        GetCount();
                        Process();
                        if (time == 0)
                        {
                            DataAna.Text = "Image";
                            timer2.Stop();
                            MessageBox.Show("灰度图像已完成");
                        }
                    }
                }
                catch (Exception ex)
                {
                    richTextBox1.AppendText(ex.Message + "\n");
                }
            }
            List<TempChannel> channelLst = new List<TempChannel>();
            private void GetCount()
            {
                channelLst.Clear();
                byte[] channels;
                //time数组就是要读取的数组,长度1000左右,每1s更新一次
                long[] times;
                // 把计数差小于某个值的两个通道看作是一个像元的响应
                for (int i = 0; i < 100; i++)
                {
                    for (int j = i + 1; j < 100; j++)
                    {
                        if (Math.Abs(times[i] - times[j]) < 10000)
                        {
                            int min = Math.Min(channels[j], channels[i]);
                            int max = Math.Max(channels[i], channels[j]);
                            if (max > 32 && min < 33)
                            {
                                //chanel保存像元响应的行列位置
                                TempChannel channel = new TempChannel();
                                channel.channeli = min;
                                channel.channelj = max;
                                channelLst.Add(channel);
                            }
                        }
                    }
                }
                //像素单元序号
                foreach (var item in channelLst)
                {
                    pixel[item.channeli - 1, item.channelj - 33]++;
                }
            }
            private void Process()
            {
                if (this.InvokeRequired)
                    this.Invoke(new Action(() => {
    
                    pictureBox1.Image.Dispose();
                    pictureBox1.Image = null;
                    richTextBox2.Clear();
    
                }));
                int max = 0;
                int min = 100000;
                foreach (var num in pixel)
                {
                    if (num > max)
                    {
                        max = num;
                    }
                    if (num < min)
                    {
                        min = num;
                    }
                }
                for (int i = 0; i <= 31; i++)
                {
                    for (int j = 0; j <= 31; j++)
                    {
                        if (pixel[i, j] != 0)
                        {
                            int num = i * 32 + j + 1;
                            richTextBox2.AppendText("第" + i + 1 + "行  第" + j + 1 + "列像元的计数为" + pixel[i, j] + "     ");
                        }
                        double index = 1000 * (pixel[i, j] - min) / (max - min);
                        greyValue[i, j] = 255 - (int)index * 255 / 1000;
                        ////显示
                        Bitmap bmp = new Bitmap(32, 32);
                        for (int i = 0; i < 32; i++)
                        {
                            for (int j = 0; j < 32; j++)
                            {
                                int col = greyValue[j, i];
                                Color pix = Color.FromArgb(col, col, col);
                                bmp.SetPixel(i, j, pix);
                            }
                        }
    
                        if (this.InvokeRequired) this.Invoke(new Action(() => {
                            Bitmap bitmapOld = pictureBox1.Image as Bitmap;
                            pictureBox1.Image = bmp;
                            pictureBox1.Visible = true;
                            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
                            if (bitmapOld != null)
                            {
                                bitmapOld.Dispose();
                            }
    
                        }));
                    }
                }
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 12月13日
  • 已采纳回答 12月5日
  • 修改了问题 12月3日
  • 创建了问题 12月3日

悬赏问题

  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法