C#关于定时器和多线程中对控件的操作以及界面假死的现象。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#关于定时器和多线程中对控件的操作以及界面假死的现象。相关的知识,希望对你有一定的参考价值。

我想在多线程中对控件进行定时操作,每隔几百毫秒对RichTextBox控件的内容进行添加更新,但是更新了2次,界面就假死了,想问问是怎么回事,相关代码如下:
private void Form1_Load(object sender, EventArgs e)

//省略其他无关代码

timer2.Interval = 700;
timer2.Enabled = false;

多线程相关代码:

new Thread((ThreadStart)(delegate

rtxtTestResults.Invoke((MethodInvoker)delegate

rtxtTestResults.Text = "正在导入中";
rtxtTestResults.SelectAll();
rtxtTestResults.SelectionColor = Color.Green;
);
this.Invoke((MethodInvoker)delegate

timer2.Enabled = true;
);
OleDbConnection myConn = new OleDbConnection(strCon);
string strCom = " SELECT * FROM [" + name + "$] where 测试日期 = #"+date+"#";
myConn.Open();
OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn);
ds = new DataSet();
myCommand.Fill(ds);
myConn.Close();
dataGridView1.Invoke((MethodInvoker)delegate

dataGridView1.DataSource = ds.Tables[0];
);
))
.Start();
字数限制,请指点

不清楚具体原因,不过你这里面定时器没什么意义,直接用循环就行了,类似于下面的,timer2什么的代码可以删掉了,直接在formload的时候启动下面的线程

new Thread((ThreadStart)(delegate
         
while(true)

                        this.Invoke((MethodInvoker)delegate
                          
                            rtxtTestResults.Text = "正在导入中";
                            rtxtTestResults.SelectAll();
                            rtxtTestResults.SelectionColor = Color.Green;
                           // timer2.Enabled = true;//这里为什么又来一次?
              
                        OleDbConnection myConn = new OleDbConnection(strCon);
                        string strCom = " SELECT * FROM [" + name + "$] where 测试日期 = #"+date+"#";
                        myConn.Open();
                        OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn);
                        ds = new DataSet();
                        myCommand.Fill(ds);
                        myConn.Close();                        
                        dataGridView1.DataSource = ds.Tables[0];
                        );
Thread.Sleep(700);

 ))
.Start();

追问

问题中的线程是在导入按钮的Click事件里面new的。formload里面我是把timer2置的false。

追答

那没什么区别,把你定时器里的代码移出来新建个线程,用类似上面的while(true)来刷新就可以了。

参考技术A new Thread((ThreadStart)(delegate
                    
    this.Invoke(()=>
                            rtxtTestResults.Text = "正在导入中";
                            rtxtTestResults.SelectAll();
                            rtxtTestResults.SelectionColor = Color.Green;
timer2.Enabled = true;
);
                        OleDbConnection myConn = new OleDbConnection(strCon);
                        string strCom = " SELECT * FROM [" + name + "$] where 测试日期 = #"+date+"#";
                        myConn.Open();
                        OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn);
                        ds = new DataSet();
                        myCommand.Fill(ds);
                        myConn.Close();
                        this.Invoke(()=>dataGridView1.DataSource = ds.Tables[0];);
                    )).Start();

错误应该是在 timer2_Tick 里, 简单的多线成用BackgroundWorker 

BackgroundWorker 类 (System.ComponentModel)

https://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx

追问

这个是怎么回事呢:


字数限制,我的timer2_Tick的代码如图片所示:

本回答被提问者采纳
参考技术B 在子线程里面加一句this.Update();试一下

c# 定时器调用控件的事件处理事情出现卡死主界面如何解决

小弟我做一个读取串口的程序,使用了serialPort1_DataReceived接收并处理数据,把数据放入一个数组中,然后使用定时器监视其中某一些数据,然后根据监视的数据写入textbox中,这个过程中出现了把主线程卡死的现象,求大神解决?

参考技术A 用线程去做 线程方法里再做定时器事件
Thread thread = new Thread(addfyj);
thread.IsBackground = true;
thread.Start();

private void addfyj()
  
show("进入定时器....");
#region 定时器
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(aTimer_Elapsed); //定时事件的方法
aTimer.Interval = 60 * 1000; //秒数
aTimer.Enabled = true;
#endregion
参考技术B 使用线程来做 不用定时器 用线程 里面使用while死循环处理 这样就可以解决了

以上是关于C#关于定时器和多线程中对控件的操作以及界面假死的现象。的主要内容,如果未能解决你的问题,请参考以下文章

c# 多线程往datagridview会造成假死,滚动条无法滚动

VB.NET程序界面假死如何解决

C#多线程实现循环。界面会假死怎么办?

c# 定时器调用控件的事件处理事情出现卡死主界面如何解决

Winform刷新时界面假死闪烁

c# 多线程运行时出现主界面卡死现象如何解决?