【问题标题】:BinarySerializer.Serialize Exception: Index was outside the bounds of the arrayBinarySerializer.Serialize 异常:索引超出了数组的范围
【发布时间】:2017-10-24 14:20:57
【问题描述】:

我实际上得到了各种 BinarySerializer 异常,例如:

  • BinarySerializer.Serialize 异常:索引超出范围 数组。
  • BinarySerializer.Serialize 异常:内部数组不能 扩展到大于 Int32.MaxValue 的元素。
  • BinarySerializer.Serialize 异常:类型 'USC.GISResearchLab.Geocoding.Core.ReferenceDatasets.Sources.Implementations.Op enAddressPoints' 在大会 'Tamu.GeoInnovation.Geocoding.Core.ReferenceDatasets.FeatureSources, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 未标记 作为可序列化的。

这里是被调用的方法:

try
        {

            string databaseName = ((IUserManagableBatchServiceManagableWebApplicationState)WebApplicationState).DatabaseManager.GetDatabaseNameFromGuid(databaseGuid);
            int databaseId = ((IUserManagableBatchServiceManagableWebApplicationState)WebApplicationState).DatabaseManager.GetDatabaseIdFromGuid(databaseGuid);
            string tableName = ((IUserManagableBatchServiceManagableWebApplicationState)WebApplicationState).DatabaseManager.GetTableNameFromGuid(tableGuid);
            int tableId = ((IUserManagableBatchServiceManagableWebApplicationState)WebApplicationState).DatabaseManager.GetTableIdFromGuid(tableGuid);
            int userId = ((IUserManagableWebApplicationState)WebApplicationState).UserManager.GetUserIdFromGuid(userGuid);

            string sql = "";
            sql += " INSERT INTO Processes ";
            sql += " (";
            ...<many column and value fields here that should not be relevant to error>
            sql += " )";
            SqlCommand cmd = new SqlCommand(sql);

            cmd.Parameters.Add(SqlParameterUtils.BuildSqlParameter("args", SqlDbType.VarBinary, BinarySerializer.Serialize(args)));
            cmd.Parameters.Add(SqlParameterUtils.BuildSqlParameter("geocoderConfiguration", SqlDbType.VarBinary, BinarySerializer.Serialize(configuration)));  

            IQueryManager qm = WebApplicationState.QueryManager;
            qm.AddParameters(cmd.Parameters);
            qm.ExecuteNonQuery(CommandType.Text, cmd.CommandText, true);
            }
            catch (Exception ex)
            {
                string msg = "Error InsertProcess Method2: " + ex.Message;
                throw new Exception(msg, ex);
            }
        }

我无法在本地重现该问题,并且经过相当长的调试时间后,无法找到所描述的任何问题。奇怪的是,在 IIS 中回收应用程序池解决了这个问题,并且该进程能够在没有错误的情况下启动。然后它稍后再次弹出,现在似乎更频繁地发生。除非我只是遗漏了一些东西,否则我无法在日志文件中找到任何相关的内容。我确信这对大多数人来说是一个显而易见的问题,但应用程序池绝对不是我的强项。如果有人可以为我指出正确的解决方案或更好的调试方向,将不胜感激。

这是 BinarySerializer 类:

 public class BinarySerializer
    {

        public static byte[] Serialize(object o)
        {

            byte[] ret = null;
            try
            {
                if (o != null)
                {
                    if (o.GetType().IsSerializable)
                    {
                        MemoryStream ms = new MemoryStream();
                        BinaryFormatter bf = new BinaryFormatter();

                        bf.Serialize(ms, o);
                        ret = ms.ToArray();
                    }
                    else
                    {
                        throw new Exception("BinarySerializer Exception: object is not serializable");
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("BinarySerializer.Serialize Exception: " + e.Message, e);
            }
            return ret;
        }

【问题讨论】:

  • 另一方面,您的所有错误都很清楚。首先 (3),您将无法序列化未标记为 [Serializable] 的对象。 (2) - 你的对象对于int 来说太长了。 (1) - 您试图访问不存在的数组索引。您是否尝试过真正调试您的代码?我可以告诉你很多——这不是游泳池问题。问题是您没有很好地测试您的应用程序。你从来没有经历过它在服务器上经历的“数据场景”。
  • 我想这是令人困惑的部分。这个应用程序已经工作了好几年了,几乎没有什么变化。我很好奇您如何知道它在配置序列化程序中而不是在 args 中?我已经调试了很多次,这两个对象都没有问题,一切都很好。我可以一遍又一遍地运行相同的批处理过程而不会出现问题,然后突然在第 N 次运行时,我得到了上述错误之一。错误的不一致和零星性质以及回收池似乎解决了它的事实使我相信可能存在池问题。
  • 该配置源自众多页面上的数十种方法,无法发布,因此缺少代码。考虑到完全相同的步骤,正在运行的相同文件仅偶尔会产生错误,这就是为什么我不认为这是配置问题。我还编辑了问题以包含 binaryserializer 类。
  • 关闭大门,我可以告诉你那里有内存泄漏 - 你的内存流在使用后没有关闭
  • BinarySerializer 实际上是一个比我知识渊博的人早在我来到这里之前就编写的类。感谢您指出这一点,并且一定会在代码中搜索其余类以获取类似的泄漏。

标签: c# .net iis-6


【解决方案1】:

现在我看到了你的代码,我想我知道你的案例 #3 会发生什么

BinarySerializer.Serialize 异常:在程序集“Tamu.GeoInnovation.Geocoding.Core.ReferenceDatasets.FeatureSources,版本=1.0.0.0,文化=”中键入“USC.GISResearchLab.Geocoding.Core.ReferenceDatasets.Sources.Implementations.Op enAddressPoints”中性,PublicKeyToken=null' 未标记为可序列化

考虑这段代码

[Serializable]
public class MyClass 
{
    public SubClass Child {get; set;}

    //[Serializable] //-- not serializable
    public class SubClass 
    {
        public int Id {get; set;}
        public string Name {get;set;}
    }
}

公开课课程 { 公共静态无效 Main() { var c = new MyClass(); c.Child = new MyClass.SubClass(); 字节[] 字节; 使用 (MemoryStream 流 = new MemoryStream()) { 新的 BinaryFormatter().Serialize(stream, c); 字节 = stream.ToArray(); }
Console.WriteLine("成功");
} }

现在它不会成功。但是,如果您在子类中取消注释[Serializable],它会。在您的代码中,您在此处检查父类的“可序列化”

if (o.GetType().IsSerializable)

但是孩子呢?您似乎期望某些对象不可序列化。在这种情况下,您需要递归检查类属性层次结构中的任何属性,这些属性是类,也是可序列化的。

建议:

重构您的 Serialize 方法

public static byte[] Serialize(object o)
{

    if (o != null) return null;
    if (o.GetType().IsSerializable)
        throw new Exception("BinarySerializer Exception: object is not serializable");

    byte[] ret = null;

    try
    {
        using(MemoryStream ms = new MemoryStream()
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(ms, o);
            ret = ms.ToArray();
            ms.Close(); 
        }
    catch (Exception e)
    {
        throw new Exception("BinarySerializer.Serialize Exception: " + e.Message, e);
    }

    return ret;
}

你的案例 #2

BinarySerializer.Serialize 异常:内部数组不能扩展到大于 Int32.MaxValue 元素

只是说明你的序列化太大了。

您的案例 #1

BinarySerializer.Serialize 异常:索引超出数组范围

也与太大的物体有关。

但有一件事......其中一些问题是框架中的错误。如果这是 IIS6,您似乎在旧框架上运行

【讨论】:

  • 感谢您的深入回答。我认为您对 #3 问题可能是正确的,并将尽快实施您的重构建议。另外两个更麻烦,因为减少配置根本不是一种选择。我可能会考虑将其分解为多种配置,并且肯定会更新 IIS。非常感谢!
猜你喜欢
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多