当不在UI线程中时创建参数
本文关键字:创建 参数 线程 UI | 更新日期: 2023-09-27 18:01:55
我试图防止加载表单时闪烁。我通过一个新的线程加载一个表单,然后调用回UI。但是,由于我在非UI线程上创建表单,覆盖(CreateParams)没有按预期工作。当我在UI线程上创建它时,它可以完美地工作。我怎样才能使它覆盖,当它回到UI线程?
// How the loading is done, from UI thread
Thread GetPage = new Thread(() => LoadPage<T>(panel));
public static void LoadPage<T>(Panel Panel)
{
Form form = Activator.CreateInstance(typeof(T)) as Form;
// Now invoke to UI
Panel.Invoke((MethodInvoker)delegate
{
form.TopLevel = false;
form.AutoScroll = true;
Panel.Controls.Add(form);
form.Show();
}
}
// Example of a form
public partial class Start : Form
{
protected override CreateParams CreateParams { get { CreateParams cp =
base.CreateParams; cp.ExStyle |= 0x02000000; return cp; } }
public Start()
{
}
}
考虑到您正在正确地调用UI线程,它与线程没有任何关系应该是很明显的。CreateParams返回的值实际上只在创建本机窗口时使用。这发生在Controls.Add()调用中,该调用在UI线程上运行。这方面的代码没有问题。如果您试图设置在错误线程上创建的窗口的父线程,则会导致程序崩溃。
真正的问题是您正在使用的WS_EX_COMPOSITED样式标志。合成仅支持顶级窗口。Winforms中的Form类。但是您可以通过将TopLevel属性设置为false来解决这个问题。样式标志只是停止起作用,对于客户端窗口没有其他选择。您需要将它移动到包含此子窗口的父窗体中。
不要这样做。WinForms控件必须在使用它们的线程上创建,并且必须从创建它们的线程中使用(唯一的例外是InvokeRequired
, Invoke
, BeginInvoke
和EndInvoke
)。不遵守这些基本规则将导致失败。