我正在尝试制作一个跨平台的WinForms软件,其中包含GUI和3D窗口。目前,我有一个TabControl有两个选项卡,第二个需要包含GLControl(3D窗口)。但是,当我切换到第二个选项卡时,程序在加载GLControl时挂起,大概是因为它们在同一个线程上。
我尝试使用像这样的BackgroundWorker解决它:
private void onTabSwitch(object sender, EventArgs e)
{
if (tabControl.SelectedIndex == 1)
if (area3D == null)
this.worker.RunWorkerAsync();
}
...
...
...
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
area3D = new GLControl();
area3D.Load += new EventHandler(area3D_Load);
area3D.Paint += new PaintEventHandler(area3D_Paint);
area3D.BackColor = Color.Black;
area3D.Size = new Size(438, 435);
area3D.Location = new Point(200, 0);
this.Invoke((MethodInvoker)delegate
{
secondTab.Controls.Add(area3D); // runs on UI thread
});
}
但它仍然挂起,因为第二个选项卡仍在主GUI线程上。我该如何解决这个问题?
Bottomline,我需要一个3D窗口在另一个选项卡中,它将异步加载,或者只是不会导致我的程序挂起。
答案 0 :(得分:0)
GLControl是一个WinForms控件,因此必须在主线程上创建。有各种可能的解决方案。我会按顺序尝试这些:
切换到加载速度更快的OpenTK 1.1(在Windows上速度提高2到3倍,具体取决于GPU和CPU。)
如果它只是一个GLControl,则强制在应用程序启动时创建它。缓存此实例并手动将其附加到选项卡(无论何时切换到选项卡,都不要销毁和重新创建它。)
OpenGL渲染上下文是重量级对象,因此这将是一个巨大的胜利。这可能会解决问题:
public MainForm : Form
{
readonly GLControl glControl = new GLControl();
public MainForm()
{
InitializeComponent();
glControl.CreateControl(); // Force the GLControl to be created
}
// ...
}
创建您自己的异步GLControl。 GLControl由两部分组成:System.Windows.Forms.Control(必须在主线程上创建)和OpenTK.GraphicsContext(可以在单独的线程上创建。)
相关代码可在以下网址找到:opentk/Source/GLControl/GLControl.cs:203
如您所见,这只是使用WinForms和OpenTK的公共API,因此这种方法是可行的。但是,我建议先尝试1和2,如果那些未能提高你正在寻求的性能改进,那么只能选择核解决方案。