我使用以下代码将短信发送给数据库中的所有学生
private void btnsend_Click(object sender, EventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = false;
}
if (!bgw.IsBusy)
{
bgw.RunWorkerAsync();
}
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
Invoke((MethodInvoker)delegate()
{
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;
}
}
});
Thread.Sleep(5000);
}
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = true;
}
}
我的问题是:如果发生异常,短信会被发送给学生,例如端口“COM5”不存在。我想通过按钮重试和取消向用户显示相同的系统消息。如果已经解决了问题。即插入设备用户按下重试按钮我想从同一点恢复线程,如果用户按下取消按钮,我想停止暂停的线程。
答案 0 :(得分:1)
对于这样的方案,一般的想法是你需要:
对于最后两项,使用一个可等待的对象,例如AutoResetEvent
和一个状态变量(甚至bool
将至少做),表明该任务是否应该中止。必须可以从UI线程和工作者访问这些变量:
AutoResetEvent pauseEvent(false);
bool shouldAbort;
然后工人的代码变为:
for (int i = 0; i < dt.Rows.Count; i++)
{
try
{
// your existing code goes here
}
catch (SomeException ex) // do not catch all exceptions!
{
BeginInvoke(...); // tell the UI thread something bad happened
pauseEvent.WaitOne(); // and block the worker until user gives input
if (shouldAbort)
{
// cleanup any other resources if required and then
break;
}
}
}
在BeginInvoke
行中,您应该调用一些方法向用户显示相应的消息并请求说明。 BeginInvoke
将立即返回,工作人员将通过致电AutoResetEvent
无限期阻止pauseEvent.WaitOne
。
UI方法应该询问用户,在收到回复后,它应该用<{p}}发出信号
pauseEvent
这将取消阻止工作者并允许它继续执行。由于代码的结构,这意味着它将继续循环的下一次迭代。如果您想让工作人员中止,请在信号pauseEvent.Set();
之前将shouldAbort
设置为true
。
如果在pauseEvent
块中递减i
,您还可以使代码重试抛出异常的迭代(而不是跳过它并继续下一个)。
答案 1 :(得分:1)
试试这个
private void btnsend_Click(object sender, EventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = false;
}
if (!bgw.IsBusy)
{
bgw.RunWorkerAsync();
}
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
if ((bgw.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
Invoke((MethodInvoker)delegate()
{
using (var sp = new SerialPort(cbcomport.Text))
{
try
{
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;
}
Thread.Sleep(5000);
}
catch (Exception ex)
{
if (MessageBox.Show(ex.Message, "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.Retry)
{
try
{
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;
}
Thread.Sleep(5000);
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
bgw.CancelAsync();
}
}
else
{
bgw.CancelAsync();
}
}
}
});
}
}
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (Control c in Controls)
{
c.Enabled = true;
}
}
答案 2 :(得分:0)
您必须在线程之间使用sync
个对象。
查看here,尤其是wait handlers
部分。