C#的Windows窗体应用程序中,如何实现停止按钮功能?

时间:2022-08-31 07:35:51
有一个“开始”按钮,点击之后执行的事件是:不停的扫描数据库中表的变化,然后做相应的操作(用定时器实现)。

问题是,我想在点击“停止”按钮以后,立即结束这个过程。怎么写??



我试过的方法:定义一个全局变量a,“停止”按钮里让全局变量变为false,在定时器执行前先判断a的值,然后做相应的操作。这样做出现了一个问题,如果在执行相应操作过程中点击了“停止”按钮,程序会出现卡死现象。。我分析原因可能是程序是由于同步执行的,会等到当前操作完成后再执行停止。。。


求大虾告知解决方法

6 个解决方案

#1


线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;

#2


引用 1 楼  的回复:
线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;


这样做和在dosomething 之前增加一个判断全局变量有什么区别吗?只不过你的是在后面,我的在前面。

#3


用线程去执行时时扫描数据库,当你结束的时候,将线程释放就行!

#4


引用 2 楼  的回复:
引用 1 楼 的回复:
线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;


这样做和在dosomething 之前增加一个判断全局变量有什么区别吗?只不过你的是在后面,我的在前面。

个人理解,因为这里加了一行
application.doevent();//给cpu时间相应其他操作
后,你按停止按钮时程序就会立即执行,把stop = true了,而不必等你的dosomething结束才停止

#5


可能可以用委托,
窗体加载的时候,来注册委托,

在单击开始事件的时候,触发委托,执行委托所注册的方法
,在方法里判断委托是否为Null,不为Null执行下去

在单击停止的时候,对委托进行干扰  t.my_delegate = null;也就是赋空

#6



private void button_safe_Click(object sender, EventArgs e)  //升井提示-----自动监测上井人员,发送安全升井短信给家人
        {
            button_uenabled();
            button_stop.Enabled = true;
           

            System.Timers.Timer t = new System.Timers.Timer(5000);
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_events);
            t.AutoReset = true;
            t.Enabled = true;
            t.SynchronizingObject = this;                       
        }
        public void t_events(object source, System.Timers.ElapsedEventArgs e) //定时处理事件
        {
            //int start, end;
            //start = System.Environment.TickCount;
            #region            连接打开数据库
            string connString = MessageModem.Properties.Settings.Default.ConnString;
            SqlConnection sqlConnection = new SqlConnection(connString);
            string connString2 = MessageModem.Properties.Settings.Default.ConnString2;
            SqlConnection sqlConnection2 = new SqlConnection(connString2);
            sqlConnection.Open();
            sqlConnection2.Open();
            #endregion
            
            label4.Text = "监视发送中";
            int j = 0, k = 0;

            
            SqlCommand cmd = new SqlCommand("P_wait_sender_id", sqlConnection);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataAdapter data = new SqlDataAdapter();
            data.SelectCommand = cmd;
            DataSet data2 = new DataSet();
            data.Fill(data2);
            

            for (int i = 0; i < data2.Tables[0].Rows.Count; i++)
            {
                string mysql = string.Format("select People_name,Linkman_Phone from People where People_id in"+ "(select People_id from PeopleSender where Sender_id = {0}) ", data2.Tables[0].Rows[i]["Sender_id"]);
                SqlCommand mycmd = new SqlCommand(mysql, sqlConnection2);
                SqlDataAdapter mydata = new SqlDataAdapter();
                mydata.SelectCommand = mycmd;
                DataSet mydata2 = new DataSet();
                mydata.Fill(mydata2);
                
                string telephone = mydata2.Tables[0].Rows[0]["Linkman_phone"].ToString();
                string message = string.Format("测试,{0}已经安全上井", mydata2.Tables[0].Rows[0]["People_name"]);
                
                if (CPPDLL.Sms_Send(telephone, message) == 1)
                {
                    j += 1;
                    label4.Text = string.Format("成功{0}条,失败{1}", j, k);
                }
                else
                {
                    k += 1;
                    label4.Text = string.Format("成功{0}条,失败{1}", j, k);
                }
            }
            sqlConnection.Close();
            sqlConnection2.Close();
           
        }


这个是"开始"按钮里的事件。。大体方法为,定义一个计时器,每5秒执行一次t_events函数,其中P_wait_sender_id是一个存储过程。循环中的CPPDLL.Sms_send是调用的一个函数,返回值是1或0.这个不用管。

现在我想实现“停止”按钮里的事件,点击停止以后,可以立刻从循环中跳出。

#1


线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;

#2


引用 1 楼  的回复:
线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;


这样做和在dosomething 之前增加一个判断全局变量有什么区别吗?只不过你的是在后面,我的在前面。

#3


用线程去执行时时扫描数据库,当你结束的时候,将线程释放就行!

#4


引用 2 楼  的回复:
引用 1 楼 的回复:
线程或者增加变量,比如

while(!stop)
{
...dosomething
application.doevent();//给cpu时间相应其他操作
}

停止 stop = true;


这样做和在dosomething 之前增加一个判断全局变量有什么区别吗?只不过你的是在后面,我的在前面。

个人理解,因为这里加了一行
application.doevent();//给cpu时间相应其他操作
后,你按停止按钮时程序就会立即执行,把stop = true了,而不必等你的dosomething结束才停止

#5


可能可以用委托,
窗体加载的时候,来注册委托,

在单击开始事件的时候,触发委托,执行委托所注册的方法
,在方法里判断委托是否为Null,不为Null执行下去

在单击停止的时候,对委托进行干扰  t.my_delegate = null;也就是赋空

#6



private void button_safe_Click(object sender, EventArgs e)  //升井提示-----自动监测上井人员,发送安全升井短信给家人
        {
            button_uenabled();
            button_stop.Enabled = true;
           

            System.Timers.Timer t = new System.Timers.Timer(5000);
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_events);
            t.AutoReset = true;
            t.Enabled = true;
            t.SynchronizingObject = this;                       
        }
        public void t_events(object source, System.Timers.ElapsedEventArgs e) //定时处理事件
        {
            //int start, end;
            //start = System.Environment.TickCount;
            #region            连接打开数据库
            string connString = MessageModem.Properties.Settings.Default.ConnString;
            SqlConnection sqlConnection = new SqlConnection(connString);
            string connString2 = MessageModem.Properties.Settings.Default.ConnString2;
            SqlConnection sqlConnection2 = new SqlConnection(connString2);
            sqlConnection.Open();
            sqlConnection2.Open();
            #endregion
            
            label4.Text = "监视发送中";
            int j = 0, k = 0;

            
            SqlCommand cmd = new SqlCommand("P_wait_sender_id", sqlConnection);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataAdapter data = new SqlDataAdapter();
            data.SelectCommand = cmd;
            DataSet data2 = new DataSet();
            data.Fill(data2);
            

            for (int i = 0; i < data2.Tables[0].Rows.Count; i++)
            {
                string mysql = string.Format("select People_name,Linkman_Phone from People where People_id in"+ "(select People_id from PeopleSender where Sender_id = {0}) ", data2.Tables[0].Rows[i]["Sender_id"]);
                SqlCommand mycmd = new SqlCommand(mysql, sqlConnection2);
                SqlDataAdapter mydata = new SqlDataAdapter();
                mydata.SelectCommand = mycmd;
                DataSet mydata2 = new DataSet();
                mydata.Fill(mydata2);
                
                string telephone = mydata2.Tables[0].Rows[0]["Linkman_phone"].ToString();
                string message = string.Format("测试,{0}已经安全上井", mydata2.Tables[0].Rows[0]["People_name"]);
                
                if (CPPDLL.Sms_Send(telephone, message) == 1)
                {
                    j += 1;
                    label4.Text = string.Format("成功{0}条,失败{1}", j, k);
                }
                else
                {
                    k += 1;
                    label4.Text = string.Format("成功{0}条,失败{1}", j, k);
                }
            }
            sqlConnection.Close();
            sqlConnection2.Close();
           
        }


这个是"开始"按钮里的事件。。大体方法为,定义一个计时器,每5秒执行一次t_events函数,其中P_wait_sender_id是一个存储过程。循环中的CPPDLL.Sms_send是调用的一个函数,返回值是1或0.这个不用管。

现在我想实现“停止”按钮里的事件,点击停止以后,可以立刻从循环中跳出。