将父表单传递给从类实例调用的ShowDialog

时间:2012-06-19 09:28:06

标签: c# .net winforms multithreading

我有一张表格。

在该表单中,我在新线程上创建了一个类的实例,因为它运行一些长时间运行的逻辑。该表单还使用户能够取消此逻辑/线程。

如果需要输入,该课程将打开一个新表格。

新表单有时会出现在另一种表单后面。

我在课堂上设置了一个属性:

public Form ParentForm{get;set;}

我现在可以做到:

MyForm form = new MyForm();
form.ShowDialog(ParentForm);

但是,在调用ShowDialog(ParentForm)时,我遇到了一个跨线程异常。

我知道我可以某种方式使用InvokeRequired但不确定如何使用属性。

由于

更新:尝试过这样做但仍然有例外:

MyForm form = new MyForm();
form.ShowDialog(GetParentForm()); 



private Form GetParentForm()
{
    //You have to Invoke() so you can wait for the function to return and obtain its return value.
    if (ParentForm.InvokeRequired)
    {
        return (Form)ParentForm.Invoke(new Func<Form>(() => GetParentForm()));
    }
    else
    {
        return ParentForm;
    } 
}

2 个答案:

答案 0 :(得分:1)

您的更新方法(GetParentForm)将无效,因为您正在执行ParentForm块中InvokeRequired的引用任务。您可以尝试在这样的块中包装ShowDialog调用,但我认为您仍然会遇到交叉线程错误。

您最简单的解决方法是移动创建的代码并将第二种形式显示在您的课程中,并移至ParentForm。所以不要这样:

MyForm form = new MyForm();
form.ShowDialog(ParentForm);

你会这样做:

ParentForm.showMyNewForm();

并且在ParentForm中你会得到这个:

public void showMyNewForm()
{
    MyForm form = new MyForm();
    form.ShowDialog(this);
}

如果MyForm需要在另一个线程上引用该类,则只需向showMyNewForm()添加一个参数,以便可以传入对它的引用。

您在这里尝试做的事情(创建和显示在不同线程上创建的相关连接表单)实际上与.NET中使用表单的方式背道而驰。

答案 1 :(得分:0)

您可以向表单添加异步方法。 我们这样说:

public class MyForm : Form
{
    public void ShowModalAsync()
    {
        this.Invoke(new Action(()=> {
              ShowDilaog(..);
        }));  
    }
}

并使用它,如:

MyForm form = new MyForm();
form.ShowModalAsync(...);

应该为你工作。

顺便说一下,如果您的问题 这个窗口出现在其他人的背后,请尝试使用Form.TopMost属性将其设置为true。考虑到它,是的,将使其面向其他形式,但在其他最重要的形式之前是不必要的。