1. 程式人生 > >WPF 降低.net framework到4.0

WPF 降低.net framework到4.0

.aspx spa 文件 當我 framework term 分析 ont its

原文:WPF 降低.net framework到4.0

1. 問題背景

由於xp系統上面最高只能安裝.net framework 4.0,所以公司項目需要將原來項目的.net framework版本降低到4.0,具體的降版本很簡單,只要把項目屬性中的目標框架改成4.0,編譯一下,解決一下出現的問題就可以了。但是在打包同事電腦上,登錄界面都正常出來了,但是登錄進去後,直接奔潰了。

2.解決問題

一開始檢查了項目及其依賴文件的.net framework的版本,都是4.0,直接運行的是生成文件,中間沒有更改任何文件,所以開始以下解決問題的道路。

(1)查找奔潰的dmp文件

程序的奔潰文件一般都在C:\Users\XXX\AppData\Local\CrashDumps目錄下面,可惜的是,在同事電腦上面,沒有發現崩潰文件。

(2)查找系統的事件日誌

選中桌面計算機,右擊,選擇管理,在系統工具-》事件查看器-》自定義視圖-》.NET Runtime, 雙擊,找到奔潰時間點的日誌,找到如下的錯誤信息:

Application: XXXX.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AggregateException
Stack:
at System.Threading.Tasks.TaskExceptionHolder.Finalize()

因為項目中用到Task的地方只有一處,所以註釋掉這段代碼,在同事電腦上面試了一下,果然OK,程序正常運行。下面就是要看看具體是什麽原因造成這個異常。

3. 問題原因

在stackoverflow上提到了這個問題的原因:

If you create a Task, and you don‘t ever call task.Wait() or try to retrieve the result of a Task<T>, when the task is collected by the garbage collector, it will tear down your application during finalization. For details, see MSDN‘s page on Exception Handling in the TPL.

The best option here is to "handle" the exception.

根據上面的英文,我的理解是:當你創建一個Task,沒有調用過task.Wait()或者沒有獲取它的執行結果,(如果Task中出現了未處理的異常),當這個Task被GC回收時,在GC finalization階段,會讓當前應用程序崩潰。

進一步看MSDN中的Exception Handling (Task Parallel Library):

"Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the joining thread. ···Exceptions are propagated when you use one of the static or instance Task.Wait or Task(Of TResult).Wait methods···"

翻譯:在一個task中運行的代碼拋出的未處理異常會被回傳給(創建該task的)主線程。···當你調用Task.Wait時,異常才會被回傳(給主線程)。

分析:當我們遇到的情況是沒調用Task.Wait,也就是異常沒有被回傳給主線程。下面的這句就提到了這個:

"If you do not wait on a task that propagates an exception, or access its Exception property, the exception is escalated according to the .NET exception policy when the task is garbage-collected."

譯:如果你在一個task中沒有等待異常被傳播,或者訪問它的異步特性,在task被GC回收時,該異常會遵循.NET異常策略被逐步升級。

分析:逐步升級的後果就是當前應用程序進程崩潰,對於ASP.NET程序來說,就是應用程序池崩潰。

4. 解決問題

最簡單的方法就是捕獲一下task中的異常,參考msdn中的代碼大概如下:

1 var task1 = Task.Run(() => { throw new CustomException("task1 faulted."); }).ContinueWith( t => { Console.WriteLine("{0}: {1}", t.Exception.InnerException.GetType().Name, t.Exception.InnerException.Message); }, TaskContinuationOptions.OnlyOnFaulted); Thread.Sleep(500);

WPF 降低.net framework到4.0