zoukankan      html  css  js  c++  java
  • [问题记录.dotnet]对象当前正在其他地方使用(Object is currently in use elsewhere)

    今天有同事反馈了个问题。查看日志,是在通讯框架这层序列化报错,异常消息为“对象当前正在其他地方使用“。查看异常的堆栈,是Image.Save方法引发的。

    经过简单排查,满足这些条件时会出现问题:1)返回对象中,Image类型字段的值非空且都是指向同一个Image实例;2)并发调用。


    进行单独验证,测试代码如下:

    [Serializable]
    public class ImageTest
    {
        System.Drawing.Image m_val;
    
        public System.Drawing.Image Val
        {
            get { return m_val; }
            set { m_val = value; }
        }
    }
    Image img = System.Drawing.Image.FromFile(@"D:about.png");
    Thread thread1 = new Thread(new ThreadStart(() =>
    {
        byte[] bytes;
        try
        {
            for (int i = 0; i < 10; i++)
            {
                ImageTest obj = new ImageTest();
                obj.Val = img;
                using (MemoryStream stream = new MemoryStream())
                {
                    new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(stream, obj);
                    bytes = stream.ToArray();
                }
            }
        }
        catch (Exception ex)
        {
            //...
        }
        Console.WriteLine("end.");
    }));
    Thread thread2 = new Thread(new ThreadStart(() =>
    {
        byte[] bytes;
        try
        {
            for (int i = 0; i < 10; i++)
            {
                ImageTest obj = new ImageTest();
                obj.Val = img;
                using (MemoryStream stream = new MemoryStream())
                {
                    new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(stream, obj);
                    bytes = stream.ToArray();
                }
            }
        }
        catch (Exception ex)
        {
            //...
        }
        Console.WriteLine("end.");
    }));
    thread1.Start();
    thread2.Start();


    异常:

    Type:    System.InvalidOperationException
    Message: 对象当前正在其他地方使用
              Object is currently in use elsewhere
    
    StackTrace:
       在 System.Drawing.Image.get_RawFormat()
       在 System.Drawing.Image.Save(MemoryStream stream)
       在 System.Drawing.Image.System.Runtime.Serialization.ISerializable.GetObjectData(SerializationInfo si, StreamingContext context)
       在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
       在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
       在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
       在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
       在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
       ...



    原因:Image.Save 方法不是线程安全的(很多GDI+的方法都不是线程安全的)。同时、对同一个Image对象实例进行处理,就可能会导致线程异常。

    建议:对返回值的类型做调整:如果Image字段必须要,改用byte[]类型。


    备注:其他地方遇到这个错误,可能是加锁,以确保线程安全。


  • 相关阅读:
    The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
    线程安全思考
    微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异
    从构建分布式秒杀系统聊聊分布式锁
    基于Redis实现延时队列服务
    Redis分布式锁的正确实现方式
    探究 Redis 4 的 stream 类型
    JAVA 异常分类与理解
    缓存穿透,缓存击穿,缓存雪崩解决方案分析
    分布式之数据库和缓存双写一致性方案解析(一)
  • 原文地址:https://www.cnblogs.com/fj365/p/13295452.html
Copyright © 2011-2022 走看看