2016-12-30 79 views
0

我想創建一個不同的線程Grid元素(創建整個電網是昂貴)和StackPanel通過Dispatcher更新。但無論我做什麼,調用Dispatcher總是會拋出一個InvalidOperationExceptionDispatcher.Invoke()的參數,它總是引發InvalidOperationException

這裏是我的代碼:

Grid grid = new Grid(); 
Dispatcher.Invoke(() => stackPanel.Children.Add(grid)); 

我已經試過什麼:

  1. Closing over a variable [沒工作]

    Grid grid = new Grid(); 
    Grid closedOverGrid = grid; 
    Dispatcher.Invoke(new Action(() => stackPanel.Children.Add(closedOverGrid))); 
    
  2. Using BeginInvoke [沒't work]

    //declaring this in another thread. 
    Grid grid = new Grid(); 
    AddToPanel(grid); 
    
    private void AddToPanel(Grid grid) 
    { 
        Dispatcher.BeginInvoke((Action)(() => 
        { 
         stackPanel.Children.Add(grid); 
        })); 
    } 
    
  3. Using a full declaration with DispatcherPriority [沒工作]

    Grid grid = new Grid(); 
    
    System.Windows.Application.Current.Dispatcher.BeginInvoke(
        DispatcherPriority.Background, 
        new Action(() => stackPanel.Children.Add(grid))); 
    
  4. Tried the .Freeze() method [沒工作]

    Grid grid = new Grid(); 
    grid.Freeze(); // Not possible. 
    

難道真的不可能,或我錯過了什麼嗎?感謝您的回答/評論。

+2

你不應該在非UI線程上創建'Grid'(和任何UI元素),因爲一旦你這樣做了,它就不能在UI線程上使用。這是標準的DispatcherObject行爲(請注意,當前的調度程序在構造函數中被記住並且永遠不會改變)。 –

回答

1

您只能訪問最初創建的線程上的控件因此,在後臺線程上創建控件,然後嘗試使用它或在UI線程上修改它不是一個選項。這就是爲什麼你得到一個InvalidOperationException。

難道真的不可能,還是我錯過了什麼?

它確實有可能在STA線程創建控制:

The calling thread must be STA, because many UI components require this

...但你仍然不能使用控制在另一個線程所以這在我猜想你的情況下會是毫無意義的。

所以不,你應該在同一個線程上創建所有的控件。這是創建父窗口的線程,即通常是主線程。

這條規則有一些非常有限的例外。有關詳情,請參閱以下博客文章:https://blogs.msdn.microsoft.com/dwayneneed/2007/04/26/multithreaded-ui-hostvisual/。如果您的控件不需要某種交互性,則可以使用本文中描述的HostVisual。

您也可以在自己的線程中啓動整個頂級窗口:http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/

但除此之外,在WPF應用程序中創建多個UI線程沒有任何意義。您只需簡單地使控件以某種方式呈現得更快,而不是試圖將渲染工作卸載到另一個線程,因爲這樣做不起作用。

相關問題