c# 使用了定时器却不能访问主界面的按钮

liliuteng 2012-11-12 10:25:17
小弟最近做个项目,想用隔一段时间读一次串口的数据并且显示在主界面上,最初的想法是用while死循环,里面用thread.Sleep函数做延时,后来发现这样程序一旦执行就关不掉了(程序死在while循环里了),连主界面上的其他按钮也访问不了了。 因此后来想用多线程,但新开的线程函数似乎不能访问当前窗体的线程的资源,比如不能在另外一个线程里面对当前窗体的textbox控件的text属性赋值,如果非要这么做有点麻烦,似乎要用到委托什么的。 后来又想到了可以访问窗体控件的定时器System.Windows.Forms.Timer,也就是定时一定时间更新一次textbox的text属性,但一运行程序就又卡住了(主窗体上的其他按钮包括关闭按钮都按不了了),并且我加长了定时时间和注释了一些定时触发函数里面的代码,却还是不能点击其他按钮。
求大神指点一下呀。
附:主界面如下:

部分代码为
private void BtnEnd_Click(object sender, EventArgs e)
{
if (port.IsOpen)
port.Close();
}

private void timer1_Tick(object sender, EventArgs e)
{
ComReadThread(sender);
}

public void ComReadThread(object obj)
{
while (port.IsOpen)
{
if (port.BytesToRead > 0)
{
strRecv = port.ReadExisting();
//this.text_showGps.Text += strRecv;
//text_showGps.SelectionStart = text_showGps.TextLength;
//text_showGps.ScrollToCaret();

GetGps();
if (Convert.ToDouble(Longitude) > 0)
{
if (Convert.ToDouble(Longitude) > max_lon)
max_lon = Convert.ToDouble(Longitude);
if (Convert.ToDouble(Latitude) > max_lat)
max_lat = Convert.ToDouble(Latitude);

if (Convert.ToDouble(Longitude) < min_lon && Convert.ToDouble(Longitude) > 0)
min_lon = Convert.ToDouble(Longitude);
if (Convert.ToDouble(Latitude) < min_lat && Convert.ToDouble(Latitude) > 0)
min_lat = Convert.ToDouble(Latitude);

text_maxLon.Text = max_lon.ToString();
text_maxLat.Text = max_lat.ToString();
text_minLon.Text = min_lon.ToString();
text_minLat.Text = min_lat.ToString();


double error_lat = (max_lat - min_lat) * Rj / 180; //获得纬度上的距离 L = Rj * ( lat1 -lat0 ) / 180
//获得经度上的距离 L = Rc * cos(lat0) * ( lon1 -lon0 ) / 180
double error_lon = (max_lon - min_lon) * Rc / 180 * Math.Cos(min_lat / 180);
text_error.Text = (Math.Sqrt(error_lon * error_lon + error_lat * error_lat)).ToString();
//text_error.Text = (Sqrt(error_lon * error_lon + error_lat * error_lat) * 6370000 / 60).ToString();

}
//Thread.Sleep(500);
}
}
}
...全文
679 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
liliuteng 2012-11-14
  • 打赏
  • 举报
回复
谢谢各位了,的确是我循环开多了,在timer控件响应的函数里面很二逼地加了个while,结果导致主界面不响应了,可能是之前写单片机程序写多了,while用习惯了吧。
嘶吼的蚂蚁 2012-11-13
  • 打赏
  • 举报
回复
线程中委托给窗体ui线程处理就好了 this.Invoke((EventHandler)delegate { this.button1.text="线程中调用窗体控件"; });
ooo7880000 2012-11-13
  • 打赏
  • 举报
回复
用System.Timers.Timer。。UI更新就像楼上说的用委托。invoke()
liliuteng 2012-11-13
  • 打赏
  • 举报
回复
之所以会用到timer控件,主要是接下来的任务里面可能需要做一点GPS导航,我希望能定时更新显示相对位置变化, 目前timer控件使用了之后主窗体就不能响应其他消息了,那这样的控件是用来干嘛的呢?或者说是我没用好这个控件吧,使用timer控件需要注意哪些问题呢?
hhddzz 2012-11-13
  • 打赏
  • 举报
回复
不懂串口 你的port会自动关掉吗 不会的话你这样不还是个死循环吗
绿领巾童鞋 2012-11-13
  • 打赏
  • 举报
回复
明显的WINCE 的WINFORM界面,如果用donetcf,少了很多东西,界面控件异步操作只能通过invoke 处理。
嘶吼的蚂蚁 2012-11-13
  • 打赏
  • 举报
回复
获取GPS信息的?串口只要接受处理数据,又不用给底层应答。为什么要用到timer控件? SerialPort_DataReceived事件接受数据就好了,当底层有消息发送给你的时候,会触发SerialPort_DataReceived事件
liliuteng 2012-11-13
  • 打赏
  • 举报
回复
谢谢各位的建议, 首先回复hhddzz,我的port确实没关,毕竟程序是想隔一段时间读一次port的数据,所以没必要关,当然我后来想加一个End按钮实现关port的功能,但目前问题是窗体没有响应,End按钮就失效了。 关于另外一个线程用委托去调用窗体控件,我下去再看一些书吧。 这里我还有一个问题,这里我用窗体类的一个定时器控件去更新窗体,既然定时器只是窗体的一个控件,为什么会造成窗体对其他按钮控件没有响应了呢?我的定时器触发函数没有执行很长时间啊!
Hauk 2012-11-13
  • 打赏
  • 举报
回复
在线程中访问主界面元素,需要使用invoke()的方式去调用。
hchanhc 2012-11-13
  • 打赏
  • 举报
回复
线程操作要使用委托调用窗体控件。
卧_槽 2012-11-13
  • 打赏
  • 举报
回复
你开了N多个死循环,不死才怪。
rcom10002 2012-11-13
  • 打赏
  • 举报
回复
Application.DoEvents()
mjp1234airen4385 2012-11-13
  • 打赏
  • 举报
回复
托管神马的最简单了。 别人的例子: public void button1_Click(object sender, EventArgs e) { new Thread((ThreadStart)delegate { int r = 0; this.Invoke((EventHandler)delegate { this.Text = "begin"; }); for (int i = 0; i < 10000; i++) { r++; this.Invoke((EventHandler)delegate { this.Text = r.ToString(); }); //Application.DoEvents(); } this.Invoke((EventHandler)delegate { this.Text = "end"; }); }).Start(); } private void RunThr() { this.Invoke(new MethodInvoker(delegate { this.label1.Text = "start do worker..."; })); for (int i = 0; i < 1000000; i++) Application.DoEvents(); this.Invoke(new MethodInvoker(delegate { this.label1.Text = "end do worker..."; })); }
leafmao 2012-11-13
  • 打赏
  • 举报
回复
同样求教怎么利用多线程循环读取串口 循环读取我只想到利用计时器查询读取,怎么利用多线程就不会了,楼主能分享下方法不?
liliuteng 2012-11-13
  • 打赏
  • 举报
回复
恩,好吧,虽然还是不明白Timer控件怎么用,但是先谢谢各位了,看来还是得用多线程加委托函数了处理这个问题了,我晚上就试一下。
机器人 2012-11-12
  • 打赏
  • 举报
回复
记住更新UI的,只有UI线程如果长时间更新,窗体就没有响应了。

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧