最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

当前热讯:BitMap对象当前正在其他地方使用?加锁也没用?

来源:博客园

最近在工作中遇到一个问题,就是我有多个线程会调用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(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线程对其的引用。

低级错误。。。

关键词: