2013-12-13 82 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,如果這些解決方案不能產生您正在尋求的性能改進,那麼只能採用核解決方案。