2013-12-13 52 views
0

我试图制作一个跨平台的WinForms软件,它内部有一个GUI和一个3D窗口。目前,我有两个选项卡的TabControl,第二个需要包含GLControl(3D窗口)。但是,当我切换到第二个选项卡时,程序在GLControl加载时挂起,大概是因为它们在同一个线程中。用C#,WinForms和OpenTK异步加载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线程。我该如何解决这个问题?底线,我需要一个3D窗口在另一个选项卡,将异步加载,或只是不会导致我的程序挂起。

回答

0

GLControl是一个WinForms控件,所以它必须在主线程上创建。有各种可能的解决方案。我会尝试这些,依次是:

  1. 切换到OpenTK 1.1它加载速度更快

  2. 如果它仅仅是一个单一的(2X-3X次在Windows上速度更快,这取决于GPU和CPU)。 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,如果这些解决方案不能产生您正在寻求的性能改进,那么只能采用核解决方案。