我正在尝试找到一种方法来将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
窗口不是Form
对象。这是一个自定义的第三方窗口。它有很多控件和模板与主题混合。单独调用一个新的空构造函数可能需要7秒,因此我需要在另一个线程上创建它,同时我继续加载我的主窗口。
现在我可以在窗口中调用除.Show()
之外的任何方法,这些方法由于线程创建限制而总是失败。我想远离创建线程作为一个无休止的运行线程,它将等待并读取一些对象,告诉他何时显示和隐藏窗口。
是.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对象的实例化。
答案 0 :(得分:0)
以下是使用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)
。