gpt4 book ai didi

c#-4.0 - GCHandle、AppDomains 托管代码和第 3 方 dll

转载 作者:行者123 更新时间:2023-12-04 15:58:53 25 4
gpt4 key购买 nike

我已经查看了许多关于“无法跨 AppDomains 传递 GCHandle”异常的线程,但我仍然不明白......

我正在使用由 DLL 驱动的 RFID 阅读器。我没有这个 DLL 的源代码,只有一个示例来展示如何使用它。

该示例效果很好,但我必须在另一个项目中复制一些代码才能将阅读器添加到中间件 Microsoft Biztalk。

问题是Microsoft Biztalk 的进程在另一个AppDomain 中工作。阅读器在读取标签时处理事件。但是当我在 Microsoft Biztalk 下运行它时,我得到了这个恼人的异常。

我看不到有关如何使其工作的任何解决方案...

下面是一些可能很有趣的代码:

// Let's connecting the result handlers.
// The reader calls a command-specific result handler if a command is done and the answer is ready to send.
// So let's tell the reader which functions should be called if a result is ready to send.

// result handler for reading EPCs synchronous
Reader.KSRWSetResultHandlerSyncGetEPCs(ResultHandlerSyncGetEPCs);

[...]

var readerErrorCode = Reader.KSRWSyncGetEPCs();
if (readerErrorCode == tKSRWReaderErrorCode.KSRW_REC_NoError)
{
// No error occurs while sending the command to the reader. Let's wait until the result handler was called.
if (ResultHandlerEvent.WaitOne(TimeSpan.FromSeconds(10)))
{
// The reader's work is done and the result handler was called. Let's check the result flag to make sure everything is ok.
if (_readerResultFlag == tKSRWResultFlag.KSRW_RF_NoError)
{
// The command was successfully processed by the reader.
// We'll display the result in the result handler.
}
else
{
// The command can't be proccessed by the reader. To know why check the result flag.
logger.error("Command \"KSRWSyncGetEPCs\" returns with error {0}", _readerResultFlag);
}
}
else
{
// We're getting no answer from the reader within 10 seconds.
logger.error("Command \"KSRWSyncGetEPCs\" timed out");
}
}

[...]

private static void ResultHandlerSyncGetEPCs(object sender, tKSRWResultFlag resultFlag, tKSRWExtendedResultFlag extendedResultFlag, tKSRWEPCListEntry[] epcList)
{
if (Reader == sender)
{
// Let's store the result flag in a global variable to get access from everywhere.
_readerResultFlag = resultFlag;

// Display all available epcs in the antenna field.
Console.ForegroundColor = ConsoleColor.White;
foreach (var resultListEntry in epcList)
{
handleTagEvent(resultListEntry);
}

// Let's set the event so that the calling process knows the command was processed by reader and the result is ready to get processed.
ResultHandlerEvent.Set();
}
}

最佳答案

您在使用 gcroot<> helper class 时遇到问题.它用在没有人可以看到的代码中,在那个 DLL 中。它经常被设计为与托管代码互操作的 C++ 代码使用,gcroot<> 存储对托管对象的引用。该类使用 GCHandle 类型来添加引用。 GCHandle.ToIntPtr() 方法返回一个 C++ 代码可以存储的指针。失败的操作是 GCHandle.FromIntPtr(),C++ 代码使用它来恢复对对象的引用。

获得此异常有两种基本解释:

  • 它可以是准确的。当您从一个 AppDomain 初始化 DLL 中的代码并在另一个 AppDomain 中使用它时,就会发生这种情况。从片段中不清楚 Reader 类对象在哪里被初始化,因此这就是解释的可能性不为零。请务必将其靠近使用 Reader 类的代码。
  • 它可能是由另一个错误引起的,该错误存在于 DLL 内的 C++ 代码中。非托管代码经常受到指针错误的影响,这种错误可能会意外覆盖内存。如果存储 gcroot<> 对象的字段发生这种情况,那么一段时间内不会出现任何问题。直到代码再次尝试恢复对象引用。此时,CLR 注意到损坏的指针值不再匹配实际的对象句柄并生成此异常。这当然是一种很难解决的错误,因为这种情况发生在您无法修复的代码中,并且向处理它的程序员展示该错误的重现非常困难,此类内存损坏问题永远无法很好地重现。

  • 首先追逐子弹#1。 Biztalk 在单独的 AppDomain 中运行您的 C# 代码的可能性很大。并且在创建 AppDomain 之前或之时,DLL 过早加载。您可以通过 SysInternals 的 ProcMon 看到一些东西。通过编写一个创建 AppDomain 并运行测试代码的小测试程序来创建此副本。如果它重现了崩溃,那么您将有一个很好的方法来向 RFID 供应商展示该问题,并且有些人希望他们会使用它并进行修复。

    与 RFID 阅读器供应商建立良好的工作关系以达成解决方案将非常重要。这从来都不是问题,总是去其他地方购物的好理由。

    关于c#-4.0 - GCHandle、AppDomains 托管代码和第 3 方 dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18379624/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com