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


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


  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/fj365/p/13295452.html
Copyright © 2020-2023  润新知