• [问题记录.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[]类型。


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


  • 相关阅读:
    Linux Centos7安装mongodb并设置开机启动
    解决Centos7下载慢的问题
    用Python处理HTML转义字符的5种方式
    java 利用poi对Excel解析读取和写入,解析resources下的.json文件
    feign.FeignException: status 404 reading DeptClientService#findAll()
    java中进程与线程的区别
    java中sigar获取信息
    Cesium 4490 解决方案
    Windows Server自动化部署Sysprep
    关于SET ANSI_PADDING的作用
  • 原文地址:https://www.cnblogs.com/fj365/p/13295452.html
Copyright © 2020-2023  润新知