【发布时间】:2016-11-10 07:53:33
【问题描述】:
我正在做一个小屏幕共享项目,在主循环中(在第二个线程上)我从连接的套接字读取数据,将其处理成一个小图像(一种块,带有X 和Y 属性指示在哪里绘制该块),并且需要在前一张图像上重新绘制它 - 它必须非常快速地更新(至少这是我的目标)。
到目前为止,我从初始图像创建了Graphics,并使用Graphics.DrawImage 方法在当前图像上绘制了较小的块(不断从套接字接收)。
看起来是这样的:
private void MainScreenThread()
{
ReadData();
initial = bufferToJpeg();
while (true)
{
int pos = ReadData();
x = BlockX();
y = BlockY();
Bitmap block = bufferToJpeg();
Draw(block,new Point(x,y));
this.Invoke(new Action(() => pictureBox1.Refresh()));
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
lock (initial)
{
e.Graphics.DrawImage(initial, 0, 0);
}
}
我做了一些基准测试,我发现DrawImage 方法运行速度很慢。
绘制 800X500 图像的平均时间为 ~520ms~。
我决定自己实现一个更快的方法,使用不安全的指针来更快地访问。
private unsafe void Draw(Bitmap bmp2, Point point)
{
lock (initial)
{
BitmapData bmData = initial.LockBits(new Rectangle(0, 0, initial.Width, initial.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, initial.PixelFormat);
BitmapData bmData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp2.PixelFormat);
IntPtr scan0 = bmData.Scan0;
IntPtr scan02 = bmData2.Scan0;
int stride = bmData.Stride;
int stride2 = bmData2.Stride;
int Width = bmp2.Width;
int Height = bmp2.Height;
int X = point.X;
int Y = point.Y;
for (int y = 0; y < Height; y++)
{
byte* p = (byte*)scan0.ToPointer();
p += (Y + y) * stride + X * 4;//setting pointer according the smaller bitmap bounds.
byte* p2 = (byte*)scan02.ToPointer();
p2 += stride2 * y;
for (int x = 0; x < Width; x++)
{
p[0] = p2[0];//B
p[1] = p2[1];//G
p[2] = p2[2];//R
p += 4;//advance pointer +4
p2 += 4;//advance pointer +4
}
}
initial.UnlockBits(bmData);
bmp2.UnlockBits(bmData2);
}
}
现在调用看起来像这样:
while (true)
{
int pos = ReadData();
x = BlockX();
y = BlockY();
Bitmap block = bufferToJpeg();
Draw(block,new Point(x,y));
this.Invoke(new Action(() => pictureBox1.Refresh()));
}
但我一直收到一个
对象当前在别处使用
当我锁定初始图像时..在这一行
BitmapData bmData = initial.LockBits(new Rectangle(0, 0, initial.Width, initial.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, initial.PixelFormat);
我不确定为什么会发生这种情况..我没有从任何其他来源访问 initial...
我将不胜感激。
谢谢。
【问题讨论】:
-
加锁的时候,能不能先用这个语句:
lock(initial)再lock(bmp2)?
标签: c# multithreading sockets thread-safety