BitMap对象当前正在其他地方使用?加锁也没用?
  DNydBo3m0qbh 2023年11月02日 62 0

最近在工作中遇到一个问题,就是我有多个线程会调用bitmap对象,运行的时候报错,对象当前正在其他地方使用。第一反应肯定是加锁啊,于是我就在每个用到bitmap的地方都加了锁,但是运行之后依然报这个错

 

 测试代码如下

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace BitMapLockTest
{
    public partial class Form1 : Form
    {
        private Bitmap testBitmap;

        private static readonly object obj = new object();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            testBitmap = new Bitmap(100, 100);
            Thread th = new Thread(DrawBackGround);
            th.IsBackground = true;
            th.Start();
        }

        private void DrawBackGround()
        {
            while (true)
            {
                lock (obj)
                {
                    Graphics g = Graphics.FromImage(testBitmap);
                    g.Clear(Color.White);
                    g.Dispose();
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            lock (obj)
            {
                Graphics g = Graphics.FromImage(testBitmap);
                g.FillRectangle(new SolidBrush(Color.FromArgb(100, 200, 2)), new Rectangle(new Point(0, 0), new Size(20, 20)));
                g.Dispose();

                Updatepic(testBitmap);
            }
        }

        private void Updatepic(Bitmap bitmap)
        {
            if (pictureBox1.InvokeRequired)
            {
                Invoke(new Action<Bitmap>(Updatepic), bitmap);
            }
            else
            {
                lock (obj)
                {
                    pictureBox1.Image = bitmap;
                }
            }
        }
    }
}

网上也有之类的问题,都是告诉我,不应该多线程使用bitmap对象,如果有需求,可以用bitmap.clone(). 

改了下

   private void button1_Click(object sender, EventArgs e)
        {
            lock (obj)
            {
                Graphics g = Graphics.FromImage(testBitmap);
                g.FillRectangle(new SolidBrush(Color.FromArgb(100, 200, 2)), new Rectangle(new Point(0, 0), new Size(20, 20)));
                g.Dispose();

                Updatepic((Bitmap)testBitmap.Clone());
            }
        }

OK,不报错了。但我的疑问没解除啊

你得告诉我为啥锁不住啊?难道是lock(obj)写的不对?那我换成 lock (testBitmap)总行了吧,依然报错。。。

后来我想了下。终于想明白了

问题出来这里

pictureBox1.Image = bitmap;

bitmap是个引用对象,把他赋值给pictureBox1的Image属性之后。pictureBox1所在的UI线程就一直保持了对bitmap对象的引用。所以别的线程加了锁也没用,依然会报错。

用clone方法复制对象的根本原因,就是避免了UI对原对象的引用。

我以为在所有引用bitmap的地方都加了锁不应该有问题了,却忘了。UI线程对其的引用。

低级错误。。。

 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  NPQODODLqddb   2024年05月17日   70   0   0 .NET
  mVIyUuLhKsxa   2024年05月17日   53   0   0 .NET
  XkHDHG7Y62UM   2024年05月17日   45   0   0 .NET
  f18CFixvrKz8   2024年05月18日   87   0   0 .NET
  rBgzkhl6abbw   2024年05月18日   78   0   0 .NET
  MYrYhn3ObP4r   2024年05月17日   41   0   0 .NET
  S34pIcuyyIVd   2024年05月17日   60   0   0 .NET
  gKJ2xtp6I8Y7   2024年05月17日   50   0   0 .NET
  MYrYhn3ObP4r   2024年05月17日   39   0   0 .NET
DNydBo3m0qbh