使用C#,WinForms和OpenTK异步加载GL Control

时间:2013-12-13 15:06:55

标签: c# winforms opengl user-interface opentk

我正在尝试制作一个跨平台的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窗口在另一个选项卡中,它将异步加载,或者只是不会导致我的程序挂起。

1 个答案:

答案 0 :(得分:0)

GLControl是一个WinForms控件,因此必须在主线程上创建。有各种可能的解决方案。我会按顺序尝试这些:

  1. 切换到加载速度更快的OpenTK 1.1(在Windows上速度提高2到3倍,具体取决于GPU和CPU。)

  2. 如果它只是一个GLControl,则强制在应用程序启动时创建它。缓存此实例并手动将其附加到选项卡(无论何时切换到选项卡,都不要销毁和重新创建它。)

    OpenGL渲染上下文是重量级对象,因此这将是一个巨大的胜利。这可能会解决问题:

    public MainForm : Form
    {
        readonly GLControl glControl = new GLControl();
    
        public MainForm()
        {
            InitializeComponent();
            glControl.CreateControl(); // Force the GLControl to be created
        }
    
        // ...
    }
    
  3. 创建您自己的异步GLControl。 GLControl由两部分组成:System.Windows.Forms.Control(必须在主线程上创建)和OpenTK.GraphicsContext(可以在单独的线程上创建。)

    相关代码可在以下网址找到:opentk/Source/GLControl/GLControl.cs:203

    如您所见,这只是使用WinForms和OpenTK的公共API,因此这种方法是可行的。但是,我建议先尝试1和2,如果那些未能提高你正在寻求的性能改进,那么只能选择核解决方案。