2011-04-21 96 views
4

我們正在處理WinForm應用程序的慢啓動(這是一個大型應用程序,並且有許多控制程序集)。控件組件是DevComponents。 Ngen被應用於防止jit編譯,但是加載時間略微減少。立即顯示啓動畫面

該應用程序具有啓動畫面,但僅在應用程序啓動後的12秒內出現。有沒有辦法一次顯示啓動畫面?

我們目前的建議是創建一個輕量級的應用程序與啓動畫面,運行主應用程序在一個單獨的進程,並關閉輕量級應用程序時主應用程序的初始化完成。

+0

如果NGEN優化不顯着,我建議放棄它並保留所有JIT的好處。 – 2011-04-21 11:34:20

+1

你如何顯示啓動畫面?你能提供一個代碼示例嗎? – 2011-04-21 11:37:21

+0

它通過使用一個單獨的表單實現。 – 2011-04-21 11:45:19

回答

10

你永遠不會得到一個.NET應用程序的啓動畫面,以立即顯示 即使您已經使用程序集來消除JIT編譯時間,仍然必須等待所有.NET Framework DLL都加載到內存中。這是一個非常大的框架,並且需要花費不少的時間來加載冷啓動。沒有什麼可以真正做到的。

微軟試圖儘可能地緩解痛苦。 WindowsFormsApplicationBase class(它在Microsoft.VisualBasic命名空間中定義,但不要讓它嚇跑你;它完全可以從C#應用程序中使用)提供了用於顯示啓動畫面的內置機制。您只需將其SplashScreen property設置爲適當的形式,其他所有內容均在幕後處理。即使在冷啓動的情況下,它的響應時間也經過了極大的優化,但它仍然不會成爲。

您唯一的選擇是在非託管代碼中編寫小包裝,其唯一目的是儘快拋出初始屏幕,然後調用.NET應用程序開始啓動自身。當然,這裏的打火機越好越好。 C++是一個選項,但C可能是更好的選擇。您需要最大限度地減少必須鏈接的外部庫的數量,因此像MFC或Qt這樣的框架絕對是不可用的:您需要直接定位Windows API。

在Visual Studio團隊做類似的事情在2010年VS他們的過程available on their blog的一個非常有趣的解釋:

即使Visual Studio 2010中使用WPF其主窗口,使用WPF的啓動畫面將需要我們等待CLR和WPF初始化,然後才能在屏幕上繪製單個像素。儘管我們在.Net 4.0中對CLR和WPF啓動速度做了一些巨大的改進,但仍然不能完全匹配原始Win32的性能。因此,我們選擇了原生C++代碼和Win32作爲啓動畫面。

但我不會在這裏花太多時間。由於您通常應該給用戶啓用和關閉啓動屏幕的選項,並且大多數用戶會選擇關閉啓動屏幕,因此很多人不太可能首先看到它。任何好的優化分析器都會告訴你,這不值得優化。

1

我想說的去與你目前的建議。除非它已經完全加載到內存中,並且由於需要時間,我建議有一個加載器應用程序,它顯示啓動並執行主要的巨大應用程序(作爲子進程)。

在巨大的應用程序中,加載時終止父應用程序。順便說一下,這不會殺死孩子。

+0

一個小型的WinForms應用程序不太可能會比一個* Large * WinForms應用程序加載表單的速度快得多。這個想法是在任何一種情況下加載閃屏形式* first *,而不是以顯示主窗體開始,並且主窗體顯示閃屏。 – 2011-04-21 11:41:36

+0

咦?除了CLR之外,沒有任何依賴項的小型WinForms應用程序的加載速度將顯着高於具有大量依賴項的應用程序。你是什​​麼意思「從顯示主窗體開始,主窗體顯示啓動畫面」?你能詳細說明嗎? – 2011-04-23 08:25:11

+1

請讀我的評論給Jason Moore的回答。只有在需要時,CLR纔會加載依賴關係。除非實際使用這些外部程序集中的代碼,否則不會受到任何處罰,無論它們是否由您的應用程序引用。我的意思是,你可以顯示一個簡單的啓動畫面窗體,它不依賴於Main方法開始時的任何外部依賴,並且它將在空的WinForms應用程序中加載,就像它將一個一百個依賴。這些依賴不會被加載,直到你請求它們,這就是JIT編譯的魔力。 – 2011-04-23 08:27:37

0

我過去所做的快速和骯髒的方式是有兩個應用程序,您的主應用程序和您的splashscreen應用程序。主應用程序對於所有重量級的DLL,控件等都是正常的。splashscreen應用程序僅僅是一個應用程序和一個Windows窗體,其中所有不必要的引用DLL都從項目中剝離出來 - 實際上,您可以更進一步,請使用輕量級的.NET框架,如緊湊的.NET框架或早期版本的.NET框架(如1.X或2.0)。

你會做的是讓啓動畫面應用程序啓動並立即顯示單個啓動畫面。有一個Windows窗體計時器(設置爲100毫秒),並啓用計時器作爲窗體的Load事件的最後一行。當定時器觸發時,禁用定時器,然後啓動您的真實應用程序。如何做到這一點見this discussion。現在主應用程序將開始啓動。一旦應用程序完成初始化並可能加載第一個表單,然後讓主應用程序終止啓動屏幕應用程序。有關殺死應用程序的更多信息here

+0

目前還不清楚這如何改善情況。即使您有一個相對較小的.NET應用程序,您仍然必須等待.NET DLL和CLR加載。更重要的是,CLR足夠聰明,不會加載你不使用的程序集/被引用的DLL。如果您的啓動畫面表單不使用這些參考DLL中定義的任何控件,並且它是您在屏幕上投擲出的第一個東西,那麼它在「大」應用程序中的速度與在「小」 。 – 2011-04-21 12:02:42

+0

此外,我非常建議放棄使用計時器的建議。用戶不希望等待*更長的時間*爲您的應用程序加載,只是因爲您向他們展示廣告牌。我並不反對啓動加載時間非常長的應用程序,但延遲添加(即使只有100毫秒)是完全沒有意義的,這幾乎是無禮的。 – 2011-04-21 12:03:47

+0

我的觀點是,splashscreen應用程序不必引用原始帖子中提到的任何大型DevComponents dll。那並且瞄準一個更小。NET框架將使其更快。我假設只有主應用程序需要引用(並因此加載)所有在12秒或更長時間內使原始程序加載的DevComponents dll。 – 2011-04-21 12:18:56

5

對於用C++編寫且使用本機Windows API的輕量級可重用啓動畫面組件,請參閱Stefan Olson's splash screen。它採用了Cody Gray所暗示的方法,從單獨的非CLR流程開始,然後加載主CLR應用程序。

我不得不在我上一份工作中實現完全一樣的東西,我可以確認這種方法效果很好 - 用戶單擊開始菜單中的程序圖標和出現的初始屏幕之間的時間僅爲幾毫秒,所以感覺'即時'。

+0

您可能會考慮總結您帖子中的鏈接內容 – FabienAndre 2012-10-30 17:00:43