我使用以下代码通过compps通过gps调制解调器发送短信
Thread thread = null;
private void btnsend_Click(object sender, EventArgs e)
{
if (thread == null)
{
thread = new Thread(SendSms);
thread.IsBackground = true;
thread.Start();
}
}
private void Update(int i)
{
if(InvokeRequired)
{
this.BeginInvoke(new Action<int>(Update), new Object[] {i});
return;
}
using (var sp = new SerialPort("COM6"))
{
sp.Open();
sp.WriteLine("AT" + Environment.NewLine);
sp.WriteLine("AT+CMGF=1" + Environment.NewLine);
sp.WriteLine("AT+CMGS=\"" + dt2.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine);
sp.WriteLine(tbsms.Text + (char)26);
if (sp.BytesToRead > 0)
{
tbsentto.Text = i + 1 + " of " + dt2.Rows.Count;
}
}
}
private void SendSms()
{
for(int i = 0; i < dt2.Rows.Count; i++)
{
Update(i);
Thread.Sleep(5000);
}
thread = null;
}
我的问题是:如果我的线程正在进行中,我怎么能保持btnsend禁用,以便用户无法按btnsend将短信发送给其他收件人
答案 0 :(得分:3)
我在自己的一个项目中遇到过类似的问题。
我采用的解决方案如下:
当我为表单上的每个按钮创建后台工作程序时,我为它们分配了DoWork和RunWorkerCompleted工作线程。
然后,在单击按钮时触发的线程上,我还包括一个检查,以确保没有工作线程已经在运行(包括按钮本身触发的线程)。
所以我的代码看起来像这样:
private void XYZ_button_Click(object sender, EventArgs e)
{
/* Check no background workers are already running */
if ((XYZ_backgroundworker.IsBusy != true) &&
(PQR_backgroundworker.IsBusy != true)) /* etc, etc for any other background
workers you might have */
{
XYZ.RunWorkerAsync();
}
}
private void XYZ_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null) MessageBox.Show("Error: " + e.Error.Message);
else if (e.Cancelled == true) MessageBox.Show("Canceled!");
}
private void XYZ_DoWork(object sender, DoWorkEventArgs e)
{
//Your code here
}
我假设您知道如何创建后台工作者,但如果没有,您可以在表单设计页面的工具箱中找到它们。您只需从列表中选择它们,单击要分配给它们的按钮即可!然后,您需要做的就是转到后台工作程序的events属性并分配适当的工作线程。
在您的特定情况下,您需要做的是创建后台工作线程并将btnsend_Click
的内容移动到DoWork
线程。然后按照我上面使用的格式进行操作。
希望这会有所帮助:)
答案 1 :(得分:1)
您可以调用一个函数,在该操作结束时启用该按钮。这是一种简单的方法。但是如果你想更普遍地处理这个问题,你可以在Thread类上编写一个包装器,或者从Thread类派生一个新类。在新类中,您可以创建在线程动作完成时触发的事件。
更新 :(在Hans Passant提醒我之后)
您可以使用BackGroundWorker。它的作用与我上面解释的方式相同。注册活动WorkerCompleted,该活动将在操作完成后触发。这是一个小example
答案 2 :(得分:1)
我在GeorgePotter的帮助下找到了我的问题的解决方案。非常感谢
private void btnsend_Click(object sender, EventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = false;
}
if (bgw.IsBusy == false)
{
bgw.RunWorkerAsync();
}
}
private void Update(int i)
{
if (InvokeRequired)
{
this.BeginInvoke(new Action<int>(Update), new Object[] { i });
return;
}
using (var sp = new SerialPort(cbcomport.Text))
{
sp.Open();
sp.WriteLine("AT" + Environment.NewLine);
sp.WriteLine("AT+CMGF=1" + Environment.NewLine);
sp.WriteLine("AT+CMGS=\"" + dt.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine);
sp.WriteLine(tbsms.Text + (char)26);
if (sp.BytesToRead > 0)
{
tbsentto.Text = i + 1 + " of " + dt.Rows.Count;
}
}
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
Update(i);
Thread.Sleep(5000);
}
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = true;
}
}