C# 在特定情况下,如何取消backgroundWorker并重新启动backgroundWorker?

C# 在特定情况下,如何取消backgroundWorker并重新启动backgroundWorker?,c#,.net,winforms,C#,.net,Winforms,在表格1顶部: ExtractImages ei = new ExtractImages(); 在form1构造函数中,我第一次启动backgroundworker public Form1() { InitializeComponent(); backgroundWorker1.RunWorkerAsync(); } 嫁妆活动 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

在表格1顶部:

ExtractImages ei = new ExtractImages();
在form1构造函数中,我第一次启动backgroundworker

public Form1()
{
     InitializeComponent();

     backgroundWorker1.RunWorkerAsync();
}
嫁妆活动

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (backgroundWorker1.CancellationPending == true)
    {
       e.Cancel = true;
       return; // this will fall to the finally and close everything    
    }
    else
    {              
       ei.ProgressChanged += (senders, eee) => backgroundWorker1.ReportProgress(eee.Percentage, eee.StateText);
       ei.Init();
    }
}
进行中

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ProgressBar1.Value = e.ProgressPercentage;
    label7.Text = e.UserState.ToString();
    label8.Text = e.ProgressPercentage + "%";
}
完成

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null) { ProgressBar1.Value = 100; }
    else
    {
    }
}
在班上名列前茅

public bool WebProblem = false;

public class ProgressEventArgs : EventArgs
{
    public int Percentage { get; set; }
    public string StateText { get; set; }
}

public event EventHandler<ProgressEventArgs> ProgressChanged;

public void Init()
{
    object obj = null;
    int index = 0;
    ExtractCountires();
    foreach (string cc in countriescodes)
    {
        // raise event here
        ProgressChanged?.Invoke(obj, new ProgressEventArgs { Percentage = 100 * index / countriescodes.Count, StateText = cc });
        ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
        index += 1;
    }
    ImagesLinks();
}
我想做的是,一旦WebProblem为真,停止Init()中的循环,并停止/取消form1中的backgroundworker

然后在backgroundworker completed事件中,向标签抛出一条关于问题的消息。然后启动计时器,30秒后再次启动backgroundworker


如果异常发生,我将在catch中使用断点,然后单击继续,它将继续,但我希望一旦出现问题,停止一切,重新开始,直到中间没有任何问题。

有很多非常奇怪的东西。我建议从一开始。关于您发布内容的建议:

表单构造函数是调用
的一个非常糟糕的地方。RunWorkerAsync
;特别是如果您希望能够重新启动后台进程。如果您真的想立即启动BackgroundWorker,您应该在Form\u Load方法中调用如下内容:

 backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
你的
dowworkeventhandler
是你应该做背景工作、检查取消情况和报告结果的地方,而你没有做任何这些。你想要的是:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var result = new List<DateString>();
    var baseUri = (Uri)e.Argument;
    var countryCodes = ExtractCountries();
    foreach (var cc in countryCodes)
    {
        if (backgroundWorker1.CancellationPending)
        {
           e.Cancel = true;
           return;
        }

        result.Add(ExtractDateAndTime(new Uri(baseUri, "?region=" + cc));
    }

    e.Result = result;
}
private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Stop();
    backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        AlertUserSomehow(e.Error);
        timer1.Interval = 30000;
        timer1.Start();
        return;
    }

    DoSomethingWith((List<DateString>)e.Result);
}
不要捕获
提取日期和时间中的异常;这样做将放弃异常并继续,就好像什么都没有错一样,然后在没有警告的情况下返回错误的答案。如果要显示异常,请将其传播到
RunWorkerCompleted
事件,并检查
RunWorkerCompletedEventArgs.Error

如果要重新启动
BackgroundWorker
,如果出现错误,则需要在设计视图或表单构造函数中声明
窗体.Timer
,以及
勾选事件处理程序,例如:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var result = new List<DateString>();
    var baseUri = (Uri)e.Argument;
    var countryCodes = ExtractCountries();
    foreach (var cc in countryCodes)
    {
        if (backgroundWorker1.CancellationPending)
        {
           e.Cancel = true;
           return;
        }

        result.Add(ExtractDateAndTime(new Uri(baseUri, "?region=" + cc));
    }

    e.Result = result;
}
private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Stop();
    backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        AlertUserSomehow(e.Error);
        timer1.Interval = 30000;
        timer1.Start();
        return;
    }

    DoSomethingWith((List<DateString>)e.Result);
}
在您的
RunWorkerCompletedEventHandler中执行以下操作:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var result = new List<DateString>();
    var baseUri = (Uri)e.Argument;
    var countryCodes = ExtractCountries();
    foreach (var cc in countryCodes)
    {
        if (backgroundWorker1.CancellationPending)
        {
           e.Cancel = true;
           return;
        }

        result.Add(ExtractDateAndTime(new Uri(baseUri, "?region=" + cc));
    }

    e.Result = result;
}
private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Stop();
    backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        AlertUserSomehow(e.Error);
        timer1.Interval = 30000;
        timer1.Start();
        return;
    }

    DoSomethingWith((List<DateString>)e.Result);
}
private void backgroundWorker1\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
如果(例如错误!=null)
{
警报(例如错误);
计时器1.间隔=30000;
timer1.Start();
返回;
}
带有((列表)e.结果)的dosomething;
}

DoWork
处理程序内部连接
ProgressChanged
事件处理程序没有任何意义。两者都必须从UI线程设置。确定。。。我懂了。您有两个级别的事件。若要重新启动,则在“已完成的处理程序”中,检查是否需要重新启动。。。有什么问题?