我有一些奇怪的行为,我无法理解。
我正在使用WCF服务将文件保存到某个DB表中。WCF服务只有一个方法,它将JSON字符串作为参数。在这种情况下,JSON是一个序列化命令,其中包含List<FileData>
和其他属性。WCF服务反序列化JSON,并为此特定命令运行CommandHandler
。
一位最终用户在尝试上传一个大小为52 MB的文件时遇到了一个错误。WCF服务返回404错误。
我能够在Visual Studio中重现这一点。根据本文更改配置文件后,404就消失了。
但现在出现了一个新的异常:当命令在客户端成功序列化并由WCF成功处理时,反序列化会抛出一个OutOfMemoryException
。这是堆叠竞赛的顶部:
(布尔附加,Int32字符必需)位于Newtonsoft.Json.JsonTextReader.ReadData(布尔附加)位于Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer(Char引号)位于Newtonsoft.Json.JsonTextReader.ParseString(Char引号)位于Newtonsoft.Json.JsonTextReader.ParseValue()位于Newtonsoft.Json.JsonTextReader.ReadInternal()位于Newtonsoft.Json.JsonReader.ReadAsBytesInternal()位于Newtonsoft.Json.JsonTextReader.ReadAsBytes()在Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader阅读器、JsonContract合约、Boolean hasConverter)
我写了一个单元测试来证明这个错误。但无论如何,这个测试通过了,换句话说,没有抛出OutOfMemoryException
。
为了完整性的测试:
[TestMethod]
public void LoadBigFile_SerializeDeserialize_DoesntThrowOutOfMemoryException()
{
// Arrange
byte[] bytes = new byte[80000000];
Random r = new Random(23);
r.NextBytes(bytes);
var command = new SomeCommand(new List<FileData>
{
new FileData(
fileFullName: @"D:SomePdfFile.pdf",
modifyDate: DateTime.MaxValue,
data: bytes
)
});
var data = JsonConvert.SerializeObject(command);
// Act
var deserializedCommand =
JsonConvert.DeserializeObject<SomeCommand>(data);
// Assert
Assert.AreEqual(bytes.Length, deserializedCommand.Files.First().Data.Length);
}
因此,我抓住机会,在生产中更改了配置文件,并尝试上传相同的文件。这很管用!!!没有OutOfMemoryException
!
现在我的问题是,为什么OutOfMemoryException
只发生在Visual Studio中,而VS的同一实例中的单元测试却没有?当VisualStudio在生产中工作时,我不能在它中测试上传大文件,这感觉有点奇怪。请注意,我还尝试在"调试"模式下以"发布模式"运行。
一些细节:
- 使用Json.Net 7.0.1
- Visual Studio 2015,更新2
- WCF托管在本地IIS Express中,IIS在生产中
- Windows 10最新版本64位
- 生产服务器Windows服务器2008 R2 64位
- .Net框架4.5.2
我在单元测试中通过将byte[] bytes = new byte[80000000];
更改为byte[] bytes = new byte[52000000];
并在循环中运行(2次)来再现OutOfMemoryException
。测试运行程序是32位的。
所以回到IIS Express-我认为您使用的是32位版本。你可以在上更改
工具|选项|项目和解决方案| Web项目|使用64位版本的IIS Express