[问题记录.dotnet]对象当前正在其他地方使用(Object is currently in use elsewhere) - Image.Save
2017-02-27 14:48
405 查看
今天有同事反馈了个问题。查看日志,是在通讯框架这层序列化报错,异常消息为“对象当前正在其他地方使用“。查看异常的堆栈,是Image.Save方法引发的。
经过简单排查,满足这些条件时会出现问题:1)返回对象中,Image类型字段的值非空且都是指向同一个Image实例;2)并发调用。
进行单独验证,测试代码如下:
异常:
原因:Image.Save 方法不是线程安全的(很多GDI+的方法都不是线程安全的)。同时、对同一个Image对象实例进行处理,就可能会导致线程异常。
建议:对返回值的类型做调整:如果Image字段必须要,改用byte[]类型。
备注:其他地方遇到这个错误,可能是加锁,以确保线程安全。
经过简单排查,满足这些条件时会出现问题: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[]类型。
备注:其他地方遇到这个错误,可能是加锁,以确保线程安全。
相关文章推荐
- 删除数据库时提示数据库正在被使用,无法删除(Cannot drop database databasename because it is currently in use)的问题
- 图像对象paip.Image对象出现“对象当前正在其他地方使用或者GDI+中发生一般性错误的解决
- paip.Image对象出现“对象当前正在其他地方使用或者GDI+中发生一般性错误的解决
- 删除数据库时提示数据库正在被使用,无法删除(Cannot drop database databasename because it is currently in use)的问题
- 对象当前正在其他地方使用 异常
- 删除数据库时提示数据库正在被使用,无法删除(Cannot drop database databasename because it is currently in use)。
- FMDB多线程下"is currently in use" 或者 "database is locked" 问题
- ios FMDB多线程"is currently in use", "database is locked"问题的解决
- FMDB多线程下"is currently in use" 或者 "database is locked" 问题
- FMDB多线程下"is currently in use" 或者 "database is locked" 问题
- VC助手使用问题————all instance of the license"*" are in use .VA will be disabled
- sudo使用问题之——xxx is not in the sudoers file。
- [项目过程中所遇到的各种问题记录]ORM篇——使用NHibernate配置对象实体的一些小问题
- [项目过程中所遇到的各种问题记录]ORM篇——使用NHibernate配置对象实体的一些小问题 22
- 使用Image对象的问题
- 执行CreateObject("Scripting.FileSystemObject")代码遇到"Operation is disallowed in this session"问题
- Cannot drop the database 'databasename' because it is currently in use
- sqlserver"无法删除数据库,因为该数据库当前正在使用"问题解决
- [项目过程中所遇到的各种问题记录]ORM篇——使用NHibernate配置对象实体的一些小问题
- This installation of RMagick was configured with ImageMagick 6.5.5 but ImageMagick 6.5.7-8 is in use