我遇到了一个很奇怪的错误,我的一个自定义控件似乎创建了两个编译文件,当我尝试使用LoadControl()
动态加载它时,会失败,因为无法将一个转换为另一个 - 即使它们完全相同。我写了一条消息来查看所有内容都是相同的,只有编译后的dll不同。
System.Web.HttpUnhandledException (0x80004005):
Exception of type 'System.Web.HttpUnhandledException' was thrown. --->
System.InvalidCastException:
[A]ASP.Modules_OneProduct_MedioumImage cannot be cast to
[B]ASP.Modules_OneProduct_MedioumImage.
Type A originates from 'App_Web_kg4bazz1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'Default'
at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\80ed7513\10eb08d9\App_Web_kg4bazz1.dll'.
Type B originates from 'App_Web_oneproduct_mediumimage.ascx.d1003923.4xoxco7b, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'Default'
at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\80ed7513\10eb08d9\App_Web_oneproduct_mediumimage.ascx.d1003923.4xoxco7b.dll'.
代码
这是我按照MSDN上的说明实现后的代码:
foreach (int OneProductID in TheProductIdArrays)
{
// here is the throw.
ASP.Modules_OneProduct_MedioumImage OneProduct =
(ASP.Modules_OneProduct_MedioumImage)LoadControl(@"~/mod/OneProduct_MediumImage.ascx");
// do some work with
//OneProduct
}
之前我在不使用ASP.
的情况下加载控件,但是在出现这个bug之后,寻找解决方案时,我严格遵循了MSDN上的步骤。但无论我怎么做,这个bug仍然存在。
我已经尝试了这两种方法,分别单独尝试和组合使用(都失败了)
<%@ Register src="~/mod/OneProduct_MediumImage.ascx" tagname="OneProduct_MediumImage" tagprefix="uc1" %>
<%@ Reference Control="~/mod/OneProduct_MediumImage.ascx" %>
配置
我的 web.config 文件中,我尝试过将 maxBatchSize
设置为 20、100、1000,以及将 optimizeCompilations
设置为 true 或 false,但是 bug 仍然会出现。
<compilation debug="false" defaultLanguage="C#" batch="true"
maxBatchSize="800" batchTimeout="10800" optimizeCompilations="false"
targetFramework="4.0">
现在关于一些细节
- 错误是随机的,有时会出现编译错误,有时不会。
- 该项目很大,页面每分钟都有很多人在线查看内容,但即使没有用户在线也会出现错误。
- 运行在64位dot.net 4、集成模式下。
- 作为Web Garden运行,但也尝试过只用一个进程池(结果还是出现了同样的问题)。
- 整个项目中已经关闭了Session。
- 这些页面从2007年开始运行,但这个问题仅发生在最近一个月,不幸的是我无法找到它是如何开始或是由什么触发的,因为我晚了几天才发现。
- 只有在加载一个自定义控件时才会出现,而这个自定义控件需要耗费大量资源。
- 我已经改动了代码4次,尝试进行了小的和大的修改,但问题仍然存在。
- 我已经尝试了
optimizeCompilations
的true和false两种方式,但结果都一样。 - 我也曾停止Web服务,删除了所有临时文件,重新启动服务,但问题依然存在。
- 我尝试在application启动时在global.asax上添加了一个mutex来锁定同一时刻只编译一个文件,但这个方式也失败了。
- 一旦出现问题就无法自动修复,直到进行下一次更新之前都会一直出错。
- 我加载此自定义控件的代码存在于代码中的多个位置,在不同的页面上调用。
- 其他类似的自定义控件没有任何问题。
- 此自定义控件已禁用ViewState。
- 我尝试重新定位了一些代码,使用微小的优化更改了整个函数调用,结果还是失败了。
开发电脑上运行正常。我在web.config中添加了batch="true"
,然后错误立即出现。- 除此之外,没有其他我们无法解决的问题。该系统运行数天,进程池没有被回收,内存稳定,剩余可用内存有充足的空间。该程序已经运行了几年,但我们每天都会进行更新。
- 在相同的核心代码下,运行多个站点(类似stackexchange),所有站点都遇到了同样的随机问题。
- AutoEventWireup 是false
- 同样的方法加载另一个自定义控件也会出现这个问题。
当这个错误出现时,我现在的解决办法是强制重新编译项目,然后错误就会消失,直到下一次更新。
我已经试图解决这个问题三周了,但没有找到原因。我尝试了几乎所有我能想到的方法,但都失败了,并且错误还会出现。所以我在这里发布帖子,希望有人能帮助我找到解决方法。
最后一个问题:这个 bug 真的太疯狂了,自定义控件也是一样,对它所做的任何操作都只能在动态加载时进行,然后编译器因某些只有它知道的原因而在两个不同的时间点上出现了它,毫无规律可言。
更新1
我已经在开发人员的机器上复现了这个 bug。在那里,我发现包含此自定义控件的两个 dll 模块是不同的。
其中一个是四个自定义控件的捆绑包。另一个模块是仅包含该自定义控件。
解决方法
为了修复这个 bug,我尝试了三周,最终发现当编译器批量编译目录并将许多不同的自定义控件捆绑在同一个 dll 中时,就会出现此 bug。因此,当我尝试单独加载它时,会抛出此异常。
所以我将有问题的自定义控件移动到一个不同的目录中,并似乎暂时避免了这个问题。
更新2
问题再次出现,即使我将一些文件移动到不同的目录中。它是随机的,无法找到与它触发的内容之间明确的关联。
更新3
因为我们发现这里的主要问题是批量编译(batch="true"
),它在同一个 dll 中编译了许多自定义控件,因此,告诉编译器不要这样做的一种方法是使用 maxBatchGeneratedFileSize
参数。我将其设置为 100 并出现了问题,现在我已将其降低到 40 并进行了测试。
maxBatchGeneratedFileSize="40"
maxBatchGeneratedFileSize
参数,在批量编译时,让编译器不要将太多的控件组合在一起。 - Aristos.ascs
结尾的 "用户控件"。 - Aristos