简体   繁体   English

BackgroundWorker ShowDialog导致应用停止

[英]BackgroundWorker ShowDialog causes app to stop

I have been trying to implement a BackgroundWorker into my application, and so far, it has not gone well. 我一直在尝试在我的应用程序中实现BackgroundWorker,但到目前为止,效果并不理想。 On a new thread, I want to open up a new Form that will have a progressbar and a label to report progress, however, this is not working well. 在新线程上,我想打开一个新表单,该表单将带有进度条和一个用于报告进度的标签,但是,这种方法不能很好地工作。 When I call ShowDialog, the application does not respond any more. 当我调用ShowDialog时,该应用程序不再响应。 Is this because my code is running from my Form1, and I am showing WorkingForm? 这是因为我的代码是从Form1运行的,并且正在显示WorkingForm吗? Also, can this be implemented cleaner? 此外,这可以实现更清洁吗?

private void button14_Click(object sender, EventArgs e)
{
    List<object> param = new List<object>();
    object[] objectparams = new object[1];
    objectparams[0] = null;
    Opera opera = new Opera();
    System.Reflection.MethodInfo clearOpera = opera.GetType().GetMethod("ClearOpera");
    param.Add(clearOpera);
    param.Add(opera);
    param.Add(objectparams);
    backgroundWorker1.RunWorkerAsync(param);
}

private void button2_Click_1(object sender, EventArgs e)
{
    Browser.cancelPending = true;
}
private delegate void getnewform();

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    mainForm main = new mainForm();
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
    var variab = (bool)form.Invoke(new getnewform(main.AskForConfirmation));
        List<object> param = e.Argument as List<object>;

        List<object> result = new List<object>();
        var method = param[0] as MethodInfo;
        object[] parameters = param[2] as object[];
        if (parameters[0] == null)
        {
            result.Add(method.Invoke(param[1], null));
            result.Add(false);
        }
        else
        {
            result.Add(method.Invoke(param[1], parameters));
            if (parameters.Contains(true))
                result.Add(true);
        }
        int progress = (100 * Browser.progressValue) / Browser.progressMax;

        backgroundWorker1.ReportProgress(progress);

        // If the BackgroundWorker.CancellationPending property is true, cancel
        if (backgroundWorker1.CancellationPending)
        {
            Console.WriteLine("Cancelled");
            Browser.cancelPending = true;
        }
        e.Result = result;
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
        TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
        form.progressBar1.Value = e.ProgressPercentage;

        form.label1.Text = Browser.progressValue + "/" + Browser.progressMax;
        Application.DoEvents();
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    List<object> param = e.Result as List<object>;
    if (e.Cancelled == false && param.Contains(true))
    {
        Display.DisplayURLs(param[0] as SortableBindingList<URL>);
        TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
        MessageBox.Show("Done");

    }
    else if (e.Cancelled == false && param.Contains(false))
    {
        TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
        MessageBox.Show("Done");
    }


}

    public class mainForm
{
public void AskForConfirmation()
{
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
    var workingForm = new TestURLGUI4.WorkingForm();
    workingForm.ShowDialog(form);
    workingForm.DialogResult = DialogResult.None;

}
}

Edit: Ok, I have updated my code according to the suggestions, and now, this produces a stackoverflowexception in System.Windows.Forms.dll: 编辑:好的,我已经根据建议更新了代码,现在,这在System.Windows.Forms.dll中产生了stackoverflowexception:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    mainForm main = new mainForm();
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
        List<object> param = e.Argument as List<object>;
        List<object> result = new List<object>();
        var method = param[0] as MethodInfo;
        object[] parameters = param[2] as object[];
        if (parameters[0] == null)
        {
            result.Add(method.Invoke(param[1], null));
            result.Add(false);
        }
        else
        {
            result.Add(method.Invoke(param[1], parameters));
            if (parameters.Contains(true))
                result.Add(true);
        }
        int progress = (100 * Browser.progressValue) / Browser.progressMax;

        backgroundWorker1.ReportProgress(progress);

        // If the BackgroundWorker.CancellationPending property is true, cancel
        if (backgroundWorker1.CancellationPending)
        {
            Console.WriteLine("Cancelled");
            Browser.cancelPending = true;
        }
        e.Result = result;


}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    TestURLGUI4.Form1 form1 = (TestURLGUI4.Form1)Application.OpenForms[0];
    if (Application.OpenForms.Count >= 2)
    {
        TestURLGUI4.WorkingForm form2 = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
        form2.progressBar1.Value = e.ProgressPercentage;

        form2.label1.Text = Browser.progressValue + "/" + Browser.progressMax;
        Application.DoEvents();
    }
    else if(Application.OpenForms.Count == 1)
    {
        var workingForm = new TestURLGUI4.WorkingForm();
        workingForm.ShowDialog(form1);
    }
}

The purpose of a BackgroundWorker is to invoke code on another thread (not the UI thread). BackgroundWorker的目的是在另一个线程(不是UI线程)上调用代码。 By calling Invoke in the DoWork method, you're completely circumventing the purpose of BackgroundWorker . 通过在DoWork方法中调用Invoke ,可以完全避开BackgroundWorker的用途。 Do all your UI work before you start the worker. 在启动工作程序之前,请完成所有UI的工作。 If you need to interact with the user while the worker is working, do it in the ProgressChanged handler--it runs on the UI thread and you don't need to use Invoke in ProgressChanged . 如果您需要在工作人员正在工作与用户进行交互,请在ProgressChanged处理程序中进行操作-它在UI线程上运行,并且您不需要在ProgressChanged使用Invoke

By invoking UI work in DoWork , you run the risk of a deadlock, which will hang your program 通过在DoWork调用UI工作,您将面临死锁的风险,这将导致程序挂起

you cant run UI on other threads. 您不能在其他线程上运行UI。 Has to be on the main thread. 必须在主线程上。

Instantiate the UI before you start the new thread. 在启动新线程之前实例化UI。 In the new thread use cross thread invoke methods on the controls you want to work with. 在新线程中,对要使用的控件使用跨线程调用方法。 Look here for example http://msdn.microsoft.com/en-us/library/ms171728.aspx 例如,在这里查看http://msdn.microsoft.com/en-us/library/ms171728.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM