关于静态窗体定时器的线程运行
来源:互联网 发布:mac上玩qq游戏 编辑:程序博客网 时间:2024/06/04 20:42
最近遇到一个问题,在窗体中定义了一个静态的窗体定时器,用来查询设备的启动状态,当设备启动后,自动更新软件控件的使能,但是也是由于这个静态的定时器,导致了问题的存在。
每次更改设备时,都会重新生成一个窗体
// 增加设备信息窗口
private void btnToolSysDevInfo_Click(object sender, EventArgs e)
{
List<string> timerrunning;
//CTimerManagement CTimer = new CTimerManagement();
timerrunning = timerManager.GetEnabledTimers();
if (((timerrunning.Count == 1) && (timerrunning.Contains(CGlobalValue.CONST_STR_TIMER_IQUIRE_STATE))) || (timerrunning.Count == 0))
{
frmInfo mInfo = new frmInfo(this);//生成新的窗体
mInfo.StartPosition = this.StartPosition;
mInfo.ShowDialog(this);
}
else
{
MessageBoxEx.Show(this, Properties.Resource.STR_CLOSE_MEASURE_BEFORE_USE);
}
}
我在frmInfo中定义了
/// <summary>
/// 查询灯状态信息的定时器
/// </summary>
private static System.Windows.Forms.Timer m_QryTimer;
并且实例化了定时器事件:
/// <summary>
/// 查询灯状态定时器处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void m_QryTimer_Tick(object sender, EventArgs e)
{
try
{
//执行查询动作
QueryLampStatus();
//氘灯钨灯控制都已经结束,则应该停止定时器
if ((m_bD2Ctrl == false) && (m_bWCtrl == false))
{
//停止定时器
m_QryTimer.Stop();
}
m_s32TimerTickCnt++;
if (m_s32TimerTickCnt >= QRY_LAMP_STATUS_TRY_CNT)
{
//停止定时器
m_QryTimer.Stop();
//重试次数已经结束,仍然未能点亮氘灯
if (m_bD2Ctrl)
{
//允许用户再次进行点灯操作
m_bD2Ctrl = false;
UpdateD2CtrlDisp();
}
//重试次数已经结束,仍然未能点亮钨灯
if (m_bWCtrl)
{
//允许用户再次进行点灯操作
m_bWCtrl = false;
UpdateWCtrlDisp();
}
}
}
catch
{
}
}
每次启动窗体时会判断定时器是否为空,为空则重新生成定时器,由于定时器是静态变量,所以只有第一次生成窗体时会生成定时器,其他的生成窗体都是使用之前的定时器,问题出现了,当第一次启动窗体后,定时器生成完成,然后关闭窗体,定时器并没有释放,仍然继续存在。当触发定时器使能运行时,
private void swbtnWSwitch_ValueChanged(object sender, EventArgs e)
{
m_frmMain.timerManager.DisableTimer(CGlobalValue.CONST_STR_TIMER_IQUIRE_STATE);
// 延迟200ms
System.Threading.Thread.Sleep(CGlobalValue.CONST_COM_DELAY_TIME_200MS);
m_frmMain.VisaCom.m_lstSendBuffer.Clear();
m_frmMain.VisaCom.m_lstRecvBuffer.Clear();
try
{
string strCmd;
//根据当前灯状态,决定发送的命令是开灯还是关灯
if (swbtnWSwitch.Value == true)
{
//发送开灯命令
strCmd = CGlobalCommand.STR_CMD_TUN_CTRL + CGlobalCommand.STR_CMD_BLANK + CGlobalCommand.STR_CMD_LAMP_CTRL_OPEN;
JobLogDataSet.WriteLog(LogType.WARNING, "DIAG", "Tungsten lamp", "User try to turn on the Tungsten lamp");
}
else
{
//发送关灯命令
strCmd = CGlobalCommand.STR_CMD_TUN_CTRL + CGlobalCommand.STR_CMD_BLANK + CGlobalCommand.STR_CMD_LAMP_CTRL_CLOSE;
JobLogDataSet.WriteLog(LogType.WARNING, "DIAG", "Tungsten lamp", "User try to turn off the Tungsten lamp");
}
//同时查询灯状态,便于更新显示
strCmd += CGlobalCommand.STR_CMD_SEPARATOR + CGlobalCommand.STR_CMD_LAMP_TUN_QRY;
strCmd += CGlobalCommand.STR_CMD_ENDMARK;
string strRsp;
m_frmMain.VisaCom.SendCommand(strCmd, CGlobalValue.CONST_COM_WAIT_TIME_2000MS, out strRsp);
//解析返回值
if (strRsp != null)
{
UpdateWLampInfo(strRsp);
if (swbtnWSwitch.Value == true)
{
//发送控制命令以后需要等待一段时间才能操作
swbtnWSwitch.Enabled = false;
//Begin:Added by lianzhonglin Bug1617 20130703
//钨灯启动时,停止氘灯和钨灯的操作
swbtnD2Switch.Enabled = false;
//End:Added by lianzhonglin
m_bWCtrl = true;
//启动定时器
m_s32TimerTickCnt = 0;
m_QryTimer.Start();//定时器触发
MessageBoxEx.Show(Properties.Resource.STR_INFO_LAMP_CTRL_WAIT);
}
else
{
//关灯命令可以立即执行完成
QueryLampStatus();
//Begin:Added by lianzhonglin Bug1617 20130703
//关灯操作时等待1s
Thread.Sleep(1000);
//End:Added by lianzhonglin
}
}
}
catch
{
}
m_frmMain.timerManager.EnableTimer(CGlobalValue.CONST_STR_TIMER_IQUIRE_STATE, true);
}
private void swbtnD2Switch_ValueChanged(object sender, EventArgs e)
{
m_frmMain.timerManager.DisableTimer(CGlobalValue.CONST_STR_TIMER_IQUIRE_STATE);
// 延迟200ms
System.Threading.Thread.Sleep(CGlobalValue.CONST_COM_DELAY_TIME_200MS);
m_frmMain.VisaCom.m_lstSendBuffer.Clear();
m_frmMain.VisaCom.m_lstRecvBuffer.Clear();
try
{
string strCmd;
//根据当前灯状态,决定发送的命令是开灯还是关灯
if (swbtnD2Switch.Value == true)
{
//发送开灯命令
strCmd = CGlobalCommand.STR_CMD_DEU_CTRL + CGlobalCommand.STR_CMD_BLANK + CGlobalCommand.STR_CMD_LAMP_CTRL_OPEN;
JobLogDataSet.WriteLog(LogType.WARNING, "DIAG", "Deuterium lamp", "User try to turn on the Deuterium lamp");
}
else
{
//发送关灯命令
strCmd = CGlobalCommand.STR_CMD_DEU_CTRL + CGlobalCommand.STR_CMD_BLANK + CGlobalCommand.STR_CMD_LAMP_CTRL_CLOSE;
JobLogDataSet.WriteLog(LogType.WARNING, "DIAG", "Deuterium lamp", "User try to turn off the Deuterium lamp");
}
//同时查询灯状态,便于更新显示
strCmd += CGlobalCommand.STR_CMD_SEPARATOR + CGlobalCommand.STR_CMD_LAMP_DEU_QRY;
strCmd += CGlobalCommand.STR_CMD_ENDMARK;
string strRsp;
m_frmMain.VisaCom.SendCommand(strCmd, CGlobalValue.CONST_COM_WAIT_TIME_2000MS, out strRsp);
//解析返回值
if (strRsp != null)
{
UpdateD2LampInfo(strRsp);
if (swbtnD2Switch.Value == true)
{
//发送控制命令以后需要等待一段时间才能操作
swbtnD2Switch.Enabled = false;
//Begin:Added by lianzhonglin Bug1617 20130703
//氘灯启动时,停止氘灯和钨灯的操作
swbtnWSwitch.Enabled = false;
//End:Added by lianzhonglin
m_bD2Ctrl = true;
//启动定时器
m_s32TimerTickCnt = 0;
m_QryTimer.Start();//定时器触发
MessageBoxEx.Show(Properties.Resource.STR_INFO_LAMP_CTRL_WAIT);
}
else
{
//关灯命令可以立即执行完成
QueryLampStatus();
//Begin:Added by lianzhonglin Bug1617 20130703
//关灯操作时等待1s
Thread.Sleep(1000);
//End:Added by lianzhonglin
}
}
}
catch
{
}
m_frmMain.timerManager.EnableTimer(CGlobalValue.CONST_STR_TIMER_IQUIRE_STATE, true);
}
即使关闭窗体,定时器线程仍然存在,会挂靠在主线程中运行(Main())。当再次打开窗体时,对控件进行操作,并用定时器更新使能时,通过监视器发现即使在新的窗体中将 swbtnD2Switch.Enabled = false; swbtnWSwitch.Enabled = false;当运行到m_QryTimer_Tick()函数时会自动的将swbtnD2Switch.Enabled = true;swbtnWSwitch.Enabled = true;原因是第一次窗体关闭后,线程仍然存在,会继续执行定时器事件,同时更新第一次打开的页面的控件使能,无论后续打开多少次,定时器事件只更新第一次的窗体控件使能,后续打开的窗体的使能不会再被更新了。
修改的方法有很多:
1、只定义一次窗体生成,当关闭时,隐藏窗体;
2、将静态的定时器改为非静态(但是这不是我要的效果);
3、每次生成新的窗体时,查看定时器使能是否为false;即执行了stop事件,然后重新生成定时器
if (m_QryTimer != null && m_QryTimer.Enabled == false)
{
m_QryTimer = null;
}
这种方法能解决部分问题,但是还不完全。
- 关于静态窗体定时器的线程运行
- 关于内核定时器,DPC,线程的使用
- 关于线程与定时器的好文章!!
- 关于内核定时器,DPC,线程的使用
- 关于线程定时器Timer的启动
- QT中使用另外的线程运行定时器
- QT中使用另外的线程运行定时器
- 关于移动端浏览器定时器后台停止运行的问题
- 关于不同窗体之间的控件查询 - 方式一(静态的窗体数组)
- ???C#中关于多个窗体的运行
- 关于oracle创建定时器和定时器创建成功后不运行的问题解决
- 关于C#Winform线程调用窗体的使用方法以及窗体的单一显示
- 1-用线程运行"Hello World"窗体
- QT中使用另外的线程运行定时器(不用新建QThread子类)
- 关于Symbian的定时器
- 关于定时器的pending
- 关于libevent的定时器
- 关于定时器的总结
- JSP技术模型(二)JSP页面生命周期
- 像素、分辨率与图片大小
- Android NDK 中使用C++源文件和使用C文件的不同
- 局域网共享mysql
- linux内核源码阅读之facebook硬盘加速利器flashcache之一
- 关于静态窗体定时器的线程运行
- C++及Windows异常处理(try,catch; __try,__finally; __try, __except)——一道笔试题引起的探究
- 我来报道的,
- Linux内核启动分析之初始化临时页表
- Android手机分辨率基础知识(DPI,DIP计算)
- error : 'AddString' : is not a member of 'CWnd'
- DBCC CHECKDB用法 手工修复数据库
- JTabbedPane的扩展,可关闭,可预览(学习了)
- php preg_match正则函数的使用注意