c#多线程-共享位图、锁和信号量

c#多线程-共享位图、锁和信号量,c#,multithreading,bitmap,locking,C#,Multithreading,Bitmap,Locking,目前我有一个带有pictureBox的表单。该窗体围绕光标绘制3个圆形轨道。每个“轨道”都是一个单独的对象,根据轨道的特定参数,每旋转1度,它就有自己的线程更新位置。在主程序中,我为每个轨道调用绘图函数,这取决于最快的轨道,所以它不会结巴 现在,一切都很好,但我不能让位图一次只被一个线程访问。添加信号量/锁会延迟“当前在别处使用”错误,但不会阻止它。锁(/信号量)传递给构造函数中的每个轨道 以下是在刷新显示时调用的更新代码: private void UpdateDisplay() {

目前我有一个带有pictureBox的表单。该窗体围绕光标绘制3个圆形轨道。每个“轨道”都是一个单独的对象,根据轨道的特定参数,每旋转1度,它就有自己的线程更新位置。在主程序中,我为每个轨道调用绘图函数,这取决于最快的轨道,所以它不会结巴

现在,一切都很好,但我不能让位图一次只被一个线程访问。添加信号量/锁会延迟“当前在别处使用”错误,但不会阻止它。锁(/信号量)传递给构造函数中的每个轨道

以下是在刷新显示时调用的更新代码:

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));