繁体   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