簡體   English   中英

.net 標准庫在 .net 核心中失敗,但在框架中失敗

[英].net standard library fails in .net core but not in framework

我們必須使用來自 3rd 方供應商(perforce)的 api。 直到今天,我們都能夠在 .net 框架應用程序中引用和使用該 API。 但是,現在我們正在重構我們的產品,當然我們決定使用新的 .net 環境,即 .net core 2.2。 由於 Perforce 沒有為 .net core 發布該庫,我們決定將該庫移植到 .net 標准。

所以,簡而言之,我們下載了源代碼,移植並添加到 .net core 項目中作為參考。

到現在為止還挺好。 奇怪的是,在對該庫進行了一些使用后,我們從該庫中獲取了ExecutionEngineException ,這會觸發Environment.Failfast並終止應用程序。

一個更重要的信息是該庫使用另一個本機庫(p4bridge.dll)。

例外是這樣的:

FailFast:
A callback was made on a garbage collected delegate of type 'p4netapi!Perforce.P4.P4CallBacks+LogMessageDelegate::Invoke'.

   at Perforce.P4.P4Bridge.RunCommandW(IntPtr, System.String, UInt32, Boolean, IntPtr[], Int32)
   at Perforce.P4.P4Bridge.RunCommandW(IntPtr, System.String, UInt32, Boolean, IntPtr[], Int32)
   at Perforce.P4.P4Server.RunCommand(System.String, UInt32, Boolean, System.String[], Int32)
   at Perforce.P4.P4Command.RunInt(Perforce.P4.StringList)
   at Perforce.P4.P4CommandResult..ctor(Perforce.P4.P4Command, Perforce.P4.StringList)
   at Perforce.P4.P4Command.Run(Perforce.P4.StringList)
   at Perforce.P4.Client.runFileListCmd(System.String, Perforce.P4.Options, System.String, Perforce.P4.FileSpec[])
   at Perforce.P4.Client.SyncFiles(System.Collections.Generic.IList`1<Perforce.P4.FileSpec>, Perforce.P4.Options)

我已經知道與garbage collected delegate相關的消息。 看起來,在某個地方,指向委托的指針被傳遞給非托管庫,然后 GC 收集它。

我們看一下那個api的源代碼。 我們看到了一些可能導致該錯誤的地方。 但是,這只是一個想法。

在調查故障時,我們創建了另一個引用該移植庫的 .net 框架應用程序,然后我們沒有在 .net 框架中遇到任何錯誤。

我的問題是:

  1. .net framework 和 .net core 在垃圾收集器機制方面有什么區別嗎?
  2. .net 框架和 .net 核心怎么可能以不同的方式對同一個庫做出反應?

我想發布我的問題的答案,因為我已經解決了這個問題。 當您現在閱讀我的答案時,這意味着您遇到了類似的問題。 首先,我要感謝@MarcGravell的評論,並向您推薦閱讀評論。

首先,想總結一下第二個問題的答案:

.net 框架和 .net 核心怎么可能以不同的方式對同一個庫做出反應?

老實說,乍一看,我認為 .net 標准庫在任何地方都會以相同的方式運行。 但是,當然我錯了。

讓我們從.Net Standard的“定義”開始。 .NET Standard只不過是一種規范(將其視為一個接口) ,它只是根據版本聲明特定平台公開的類型和 API。

如果您看一下,您將看到您的標准庫引用了 .NET Standard SDK,其中包含一個包含 API 的netstandard.dll ,或者更netstandard.dll ,是合同,我們可以在庫項目中使用。 如果您查看帶有Ildasm.exe的標准庫,您將看到它使用的是.netstandard.dll

在此處輸入圖片說明

讓我們檢查一下我們的核心和框架應用程序如何使用它。 在核心方面,它比框架更有效。

我一直是圖表的粉絲:

在此處輸入圖片說明

正如您在圖中看到的,核心和框架應用程序都引用了它們自己的netstandard.dll 這些庫是基於type forwarding概念構建的。 對於核心應用程序, BCL類型由System.Runtime.dll提供,而對於框架應用程序, BCL類型由mscorlib.dll提供。 所以,兩種不同的實現

例如,這里是核心應用程序將使用的.netstandard庫的 IL 代碼:

在此處輸入圖片說明

從 msdn閱讀有關類型轉發的更多信息。

有關.NET Standard的詳細信息來源


現在有點關於我的第一個問題:

.net framework 和 .net core 在垃圾收集器機制方面有什么區別嗎?

其實微軟不斷演進GC機制也不足為奇。


現在我如何解決這個問題:

好消息是我移植到標准的那個庫是開源的。 我調查了這個問題,簡而言之,他們正在將委托指針傳遞給非托管庫。 並且該非托管庫保存指針並嘗試在某個生命周期內使用它,該生命周期比該指針的生命周期更長。 實際上,有趣的一點是框架 GC 並沒有以某種方式收集該委托,這就是為什么在框架方面沒有例外。 但是,如果核心 GC 收集該委托並創建失敗的原因。 我確實改變了我設置該字段的方式,現在它可以工作了。 我將該字段聲明為靜態並在靜態構造函數中對其進行初始化,因此該委托的生命周期與應用程序生命周期一樣長。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM