c#多线程-共享位图、锁和信号量
目前我有一个带有pictureBox的表单。该窗体围绕光标绘制3个圆形轨道。每个“轨道”都是一个单独的对象,根据轨道的特定参数,每旋转1度,它就有自己的线程更新位置。在主程序中,我为每个轨道调用绘图函数,这取决于最快的轨道,所以它不会结巴 现在,一切都很好,但我不能让位图一次只被一个线程访问。添加信号量/锁会延迟“当前在别处使用”错误,但不会阻止它。锁(/信号量)传递给构造函数中的每个轨道 以下是在刷新显示时调用的更新代码:c#多线程-共享位图、锁和信号量,c#,multithreading,bitmap,locking,C#,Multithreading,Bitmap,Locking,目前我有一个带有pictureBox的表单。该窗体围绕光标绘制3个圆形轨道。每个“轨道”都是一个单独的对象,根据轨道的特定参数,每旋转1度,它就有自己的线程更新位置。在主程序中,我为每个轨道调用绘图函数,这取决于最快的轨道,所以它不会结巴 现在,一切都很好,但我不能让位图一次只被一个线程访问。添加信号量/锁会延迟“当前在别处使用”错误,但不会阻止它。锁(/信号量)传递给构造函数中的每个轨道 以下是在刷新显示时调用的更新代码: private void UpdateDisplay() {
private void UpdateDisplay()
{
// get fresh display
Lock.AcquireWriterLock(-1);
Display = (Bitmap)(Background.Clone());
Lock.ReleaseWriterLock();
// draw all orbitals
foreach (Orbital item in Orbitals)
{
item.Draw(Display);
}
// update the display
Lock.AcquireWriterLock(-1);
pictureBox1.Image = Display;
Lock.ReleaseWriterLock();
}
这是物体轨道的绘制方法:
public void Draw(Bitmap bitmap)
{
// draw a square
int maxX = OrbitalX + OrbitalSizeRadius;
int maxY = OrbitalY + OrbitalSizeRadius;
for (int i = OrbitalX - OrbitalSizeRadius; i < maxX; i++)
{
for (int j = OrbitalY - OrbitalSizeRadius; j < maxY; j++)
{
Lock.AcquireWriterLock(-1);
// check for eventual offscreen pixels
if (BoundaryControl.Check(i, j, bitmap.Width, bitmap.Height))
{
bitmap.SetPixel(i, j, OrbitalColor);
}
Lock.ReleaseWriterLock();
}
}
}
轨道内操作锁的代码:
// declaration
private ReaderWriterLock Lock;
// constructor
public Orbital(int radius, double speed, int sizeRadius, Color color, int startingRotation, bool counterClockwise, ReaderWriterLock thelock)
{
/*
* bunch of assigns
*/
Lock = thelock;
}
在Form类中:
// declaration
private ReaderWriterLock Lock;
// initialization
Lock = new ReaderWriterLock();
// passing to Orbital as an argument
// Orbitals is an ArrayList
Orbitals.Add(new Orbital(100, 10, 5, Color.IndianRed, 0, false, Lock));
谜团解开了,锁工作得很好。共享显示确实是一个问题,但解决它“揭示”了另一个隐藏的问题,它引发了完全相同的错误。您得到的错误是什么,一行是什么<代码>“当前在别处使用”没有多大帮助。。你确定你只使用了一把锁吗?也许你无意中创建了3个锁,并将一个不同的锁传递给了每个线程,而不是同一个线程。出于好奇,你选择多个线程都写入共享位图有什么特别的原因吗?我只是问,因为这种方法是非常非典型的。最常见的解决方案是让一个绘图线程遍历您的数据结构,并根据需要重新绘制所有内容。@LeeHiles,我想将绘图保留在轨道内,以防获得特定的子类绘图方法。我还必须把所有的信息放到主程序中,但那是次要的。我不知道,这似乎是个不错的主意。我认为是
pictureBox1.Image=Display
的左侧抛出的不是右侧,因为您的位图锁在我看来很好。您似乎在使用锁,因为Display
是位图,但我打赌它是从多个线程访问并抛出的pictureBox1
。尝试在任何其他pictureBox1
周围添加锁,以及对其引用的同一对象的任何其他引用。@Quantic,这可能是pictureBox1.MouseMove+=pictureBox1\u MouseMove代码>?这是我在pictureBox上做的唯一其他操作(它只更新鼠标位置以进行轨道计算),这看起来很荒谬,因为在以前的程序中,只有一个轨道包含主程序中的数据,线程更新位置和绑定到pictureBox的3个事件(将LMB保持时的半径和速度减半),一切都很完美,没有错误。
// declaration
private ReaderWriterLock Lock;
// initialization
Lock = new ReaderWriterLock();
// passing to Orbital as an argument
// Orbitals is an ArrayList
Orbitals.Add(new Orbital(100, 10, 5, Color.IndianRed, 0, false, Lock));