C# 如何在发生异常时暂停backgroundworker线程,并在发生异常时恢复该线程

C# 如何在发生异常时暂停backgroundworker线程,并在发生异常时恢复该线程,c#,windows,C#,Windows,im使用以下代码向数据库中的所有学生发送短信 private void btnsend_Click(object sender, EventArgs e) { foreach (Control c in Controls) { c.Enabled = false; } if (!bgw.IsBusy) { bgw.RunWorkerAsync();

im使用以下代码向数据库中的所有学生发送短信

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;
        }
    }
private void btn发送\u单击(对象发送者,事件参数e)
{
foreach(控件中的控件c)
{
c、 启用=错误;
}
如果(!bgw.IsBusy)
{
bgw.RunWorkerAsync();
}
}
私有void bgw_DoWork(对象发送方,DoWorkEventArgs e)
{
对于(int i=0;i0)
{
tbsentto.Text=i+1+“of”+dt.Rows.Count;
}
}
});
睡眠(5000);
}
}
私有void bgw_RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
foreach(控件中的控件c)
{
c、 启用=真;
}
}

我的问题是:在短信发送给学生的过程中,如果出现异常,例如端口“COM5”不存在。我想用“重试”和“取消”按钮向用户显示相同的系统消息。如果已经解决了问题。i、 e插入设备后,用户按下重试按钮,我想从同一点恢复线程,如果用户按下取消按钮,我想停止暂停的线程。

您必须在线程之间使用
同步
对象。
请特别查看“等待处理程序”部分。

对于此类方案,总体思路是您需要:

  • 捕获可能从工作进程抛出的异常(但是仅捕获您知道可以处理的异常;捕获所有异常是邪恶的!)
  • 通知UI线程以提示用户
  • 暂停执行,直到UI线程收到输入
  • 如果输入指示中止执行,则中止执行
对于最后两项,使用一个可等待对象,例如
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;
        }
    }
}
这将取消阻止工作进程并允许它恢复执行。由于代码的结构,这意味着它将继续循环的下一次迭代。如果要使工作进程中止,请在发出信号
pauseEvent
之前,将
shoulldabort
设置为
true

如果在
catch
块中减量
i
,也可以让代码重试引发异常的迭代(而不是跳过它并继续下一次)

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;
        }
    }
private void btn发送\u单击(对象发送者,事件参数e)
{
foreach(控件中的控件c)
{
c、 启用=错误;
}
如果(!bgw.IsBusy)
{
bgw.RunWorkerAsync();
}
}
私有void bgw_DoWork(对象发送方,DoWorkEventArgs e)
{
对于(int i=0;i0)
{
tbsentto.Text=i+1+“of”+dt.Rows.Count;
}
睡眠(5000);
}
捕获(例外情况除外)
{
if(MessageBox.Show(例如Message,“Error”,MessageBoxButtons.RetryCancel,MessageBoxIcon.Error)==System.Windows.Forms.DialogResult.Retry)
{
尝试
{
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);
如果(sp.BytesToRead>0)
{
tbsentto.Text=i+1+“of”+dt.Rows.Count;
}
睡眠(5000);
}
捕获(异常ex2)
{
MessageBox.Show(ex2.Message,“Error”,MessageBoxButtons.OK,MessageBoxIcon.Error);
bgw.CancelAsync();
}
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;
        }
    }