更改窗体的父线程

Change parent thread of a form

我正在尝试找到一种方法将 winform 线程的父线程更改回 GUI 线程。现在我必须从另一个线程创建表单,但无法从引用它的主表单访问。

这里是我所拥有的示例

public partial class MainForm : Form
{
    // local instance of the sub form
    private ViewForm SubForm { get; set;} = null;

    public MainForm()
    {
        InitializeComponent();

        Task.Run(() =>
        {
            // set the sub form             
            SubForm = new ViewForm();
        }

        // call the rest of the initialization of main form
        InitializeCustomControls();
    }

    private void OpenViewWindow_Click(object sender, EventArgs e)
    {
        // if the window is instanciated
        if (SubForm != null)
        {
            SubForm.Show();                
        }
    }        
}

ViewForm window 不是 Form 对象。这是自定义第三方 window。它有很多与主题混合的控件和模板。对一个新的空构造函数的唯一调用最多可能需要 7 秒,因此为什么我需要在另一个线程上创建它,同时继续加载我的主 window.

现在我可以调用 window 中的任何方法,但 .Show() 除外,它总是由于线程创建限制而失败。我想避免将线程创建为无休止的 运行 线程,该线程将等待并读取一些对象以告诉他何时显示和隐藏 window.

这是 .Show() 错误:

Cross-thread operation not valid: Control 'ViewForm' accessed from a thread other than the thread it was created on.

我确实尝试了以下方法,但它仍然冻结了我的界面:

Task.Run(() =>
{
    // set the sub form   
    this.Invoke(new MethodInvoker(delegate
    {
        SubForm = new ViewForm();
    }));
}

我想要的是像火一样忘记 GUI 对象的实例化。

这是一个使用 BackGroundWorker 的解决方案:

public partial class MainForm : Form
{
    // local instance of the sub form
    private ViewForm SubForm { get; set;} = null;

    public MainForm()
    {
        InitializeComponent();
        backGroundWorker1.RunWorkerAsync();
        InitializeCustomControls();
    }

    private void OpenViewWindow_Click(object sender, EventArgs e)
    {
        // if the window is instanciated
        if (SubForm != null)
        {
            SubForm.Show();                
        }
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        SubForm = new ViewForm();
    }
}

已测试创建两种形式,MainForm 与示例中的非常相似,SubView 形式在构造函数中带有 Threading.Sleep(10000)