2011-08-29 107 views
1

我有很大的應用程序設計不好。特別是在開始時,它正在UI線程中初始化許多服務。問題是初始化可能很耗時,所以UI線程在此期間凍結。我無法將它移動到後臺線程,因爲有些服務依賴於它們啓動的線程,並且只有太多的代碼來檢查它是如何逐行進行的。有沒有辦法來隔離WPF中使用的資源?

的想法是與獨立調度單獨的線程來顯示加載屏幕與進度:

ThreadStart initLoadingDialog =() => 
            { 
             _currentDispatcher = Dispatcher.CurrentDispatcher; 
             _dialogWindow = new MyDialogWindow(); 
             _dialogWindow.Show(); 
             Dispatcher.Run(); 
            }; 
var thread = new Thread(initLoadingDialog); 
thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

(當然,代碼是不完全準確的,因爲我使用MVVM而且也沒有MyDialogWindowClass而只是窗口的設置內容到ViewModel和DataTemplate在資源中,但這裏ASAIK並不重要)。

它的工作,但似乎使用一些資源,從而有效地綁定到非主要UI線程。後來我收到異常「無法將屬性'Background'中的值轉換爲'System.Windows.Media.Brush'類型的對象。調用線程無法訪問此對象,因爲不同的線程擁有它。錯誤對象'System.Windows .Controls.Border'在標記文件'PresentationFramework.Aero,Version = 3.0.0.0,Culture = neutral,PublicKeyToken = 31bf3856ad364e35,ProcessorArchitecture = MSIL; component/themes/aero.normalcolor.xaml'。「

那麼,我想要的是完全隔離這個單一對話框,以便它將擁有自己的資源(實際上只有帶有ProgressBar和兩個TextBlocks的Grid),而不使用其他任何東西。有沒有辦法做到這一點?

P.S.或者,也許有人知道如何確定究竟哪個Brush資源存在問題?因爲我只有這個例外而沒有別的......這個問題的根源究竟是什麼?

UPD:它是ProgressBar。它的風格使用了一些非凍結筆刷,並綁定到線程。

回答

1

我猜測,造成你一個問題的刷子是在主UI線程上的較早時間實例化的,這就是爲什麼你看到你的錯誤。我想你可能需要重寫對話框中所有控件的控件模板,並確保你凍結了所有的畫筆。

事情是這樣的:

<LinearGradientBrush freezable:Freeze="True" 
xmlns:freezable="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
/> 

而且,我相信,調度員將繼續運行窗口關閉後。您需要手動關閉它..類似這樣的:

_dialogWindow.Closed += (sender, e) => _dialogWindow.Dispatcher.InvokeShutdown(); 
+0

不,對話框顯示正常和關閉。但是當我展示一些對話時 - 它失敗了。只需一個對話。不知道原因 - 這個具體的對話如何與其他人不同... P.S.是的,我實際上調用了'InvokeShutdown()',只是沒有在問題中暴露它。謝謝。 –

+0

無論如何,重新定義所有控件模板似乎有點工作。即使只是用於ProgressBar。我知道冷凍食品,但問題是如何從應用程序的其他部分隔離(強制創建新的應用程序),而不是如何安全地共享部分資源。 –

+0

Aero畫筆用於許多控件,我認爲一旦實例化就存儲在字典中。如果您的對話框使用該字典中已有的筆刷(在主UI線程中創建),反之亦然,您將遇到問題。 – mdm20

相關問題