XOR的位图服务器并发错误

时间:2014-09-22 20:47:52

标签: c# concurrency bitmap xor

我正在编写一个从另一台服务器获取更新的服务器,然后允许多个客户端连接并接收增量。我允许客户端要求对增量进行异或。当XOR打开时,我得到加扰数据,这意味着两个位图被错误地异或。但如果我延迟100毫秒,就没有问题了。

接收更新功能:

while (this.updateQueue != null)
{
    Frame update;
    if (!this.updateQueue.TryDequeue(out update))
    {
        Thread.Sleep(10);
        continue;
    }

    lock (this.clientFrameLock)
    {
        //For Each Client connected, if the update Area is not empty
        // Union it with the new update area
        foreach (string key in this.clientFrames.Keys)
        {
            if (this.clientFrames[key].Area.IsEmpty)
            {
                this.clientFrames[key].Area = new Rectangle(update.Area.X, update.Area.Y, update.Area.Width, update.Area.Height);
            }
            else
            {
                Rectangle area = Rectangle.Union(this.clientFrames[key].Area, update.Area);
                this.clientFrames[key].Area = area;
            }
        }
        // if update from server is XOR'd, unxor and apply it to this.CurrentFrame, else just Apply
        lock (this.currentFrameLock)
        {
            if (update.Mask == Mask.MASK_XOR) this.currentFrame.Buffer.XorBitmaps(update.Buffer, update.Area);
            else this.currentFrame.Buffer.Apply(update.Buffer, update.Area);
            this.currentFrame.Sequence++;
        }
    }
    update.Dispose();
}

客户端调用以获取下一帧的函数:

public Frame GetNextUpdateFrame(Compression compression, Mask desiredMask, string uuid)
{
    Bitmap buffer;
    Bitmap newClientBuffer;
    Bitmap lastBuffer;
    Mask actualMask = Mask.MASK_NONE;
    Rectangle rect;
    int currentFrameSequence;
    Size currentFrameResolution;
    lock (this.clientFrameLock)
    {
        lock (this.currentFrameLock)
        {
            buffer = this.currentFrame.Buffer.CopyBitmap();
            newClientBuffer = buffer.CopyBitmap();
            currentFrameSequence = this.currentFrame.Sequence;
            currentFrameResolution = this.currentFrame.Resolution;
        }
        if (!this.clientFrames.ContainsKey(uuid))
        {
           this.clientFrames.Add(uuid, new Frame(currentFrameSequence, newClientBuffer.CopyBitmap(), new Rectangle(), currentFrameResolution, Mask.MASK_NONE));
           var newClientFrame = new Frame(currentFrameSequence, newClientBuffer.CopyBitmap(), new Rectangle(0, 0, currentFrameResolution.Width, currentFrameResolution.Height), currentFrameResolution, Mask.MASK_NONE);
           buffer.Dispose();
           newClientBuffer.Dispose();
           return newClientFrame;
        }

        Frame lastFrame = this.clientFrames[uuid];
        rect = new Rectangle(lastFrame.Area.X, lastFrame.Area.Y, lastFrame.Area.Width, lastFrame.Area.Height);
        if (rect.Width == 0 || rect.Height == 0)
        {
            buffer.Dispose();
            newClientBuffer.Dispose();
            return null;
        }
        lastBuffer = lastFrame.Buffer.CopyBitmap();
    }


    if (desiredMask == Mask.MASK_XOR)
    {
        buffer.XorBitmaps(lastBuffer, rect, rect);
        actualMask = Mask.MASK_XOR;
    }


    Bitmap smallerBitmap = buffer.CopyBitmap(rect);
    buffer.Dispose();
    lastBuffer.Dispose();
    this.clientFrames[uuid].Dispose();
    this.clientFrames.Remove(uuid);
    this.clientFrames.Add(uuid, new Frame(currentFrameSequence, newClientBuffer, new Rectangle(), currentFrameResolution, Mask.MASK_NONE));
    return new Frame(currentFrameSequence, smallerBitmap, rect, currentFrameResolution, actualMask);
}

异或功能:

internal static void XorBitmaps(this Bitmap sourceBitmap, Bitmap baseBitmap, Rectangle rect, Rectangle rectBase = default (Rectangle))
{
    if (baseBitmap == null) return;
    if (rectBase == default(Rectangle))
    {
        rectBase = new Rectangle(0, 0, baseBitmap.Width, baseBitmap.Height);
    }
    BitmapData bmdSource = sourceBitmap.LockBits(rect, ImageLockMode.ReadWrite, sourceBitmap.PixelFormat);
    BitmapData bmdBase = baseBitmap.LockBits(rectBase, ImageLockMode.ReadOnly, baseBitmap.PixelFormat);
    unsafe
    {
        for (int y = 0; y < bmdSource.Height; y++)
        {
            int* rowSource = (int*)((byte*)bmdSource.Scan0 + (y * bmdSource.Stride));
            int* rowBase = (int*)((byte*)bmdBase.Scan0 + (y * bmdBase.Stride));
            for (int x = 0; x < bmdSource.Width; x++)
            {
                rowSource[x] ^= rowBase[x];
            }
        }
    }
    baseBitmap.UnlockBits(bmdBase);
    sourceBitmap.UnlockBits(bmdSource);        
}

CopyBitmap函数(使用Kernal32.dll CopyMemory)

internal static Bitmap CopyBitmap(this Bitmap bitmap)
{
int bbp = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
PixelFormat pixFormat;
    if (bbp != 0) pixFormat = bitmap.PixelFormat;
    else
    {
        pixFormat = PixelFormat.Format32bppRgb;
        bbp = 4;
    }
    Bitmap newBitmap = new Bitmap(bitmap.Width, bitmap.Height, pixFormat);
    BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, pixFormat);
    BitmapData newBitmapData = newBitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, pixFormat);
    CopyMemory(newBitmapData.Scan0, bmpdata.Scan0, (uint)(bbp * bitmap.Height * bitmap.Width));
    bitmap.UnlockBits(bmpdata);
    newBitmap.UnlockBits(newBitmapData);
    return newBitmap;
}

internal static Bitmap CopyBitmap(this Bitmap bitmap, Rectangle bounds)
{
    Bitmap newBitmap = new Bitmap(bounds.Width, bounds.Height, bitmap.PixelFormat);
    BitmapData bmdSrc = bitmap.LockBits(bounds, ImageLockMode.ReadOnly, bitmap.PixelFormat);
    BitmapData bmdDst = newBitmap.LockBits(new Rectangle(0, 0, bounds.Width, bounds.Height), ImageLockMode.ReadWrite, newBitmap.PixelFormat);
    unsafe
    {
        for (int y = 0; y < bmdSrc.Height; y++)
        {
            IntPtr rowSrc = (IntPtr)((byte*)bmdSrc.Scan0 + (y * bmdSrc.Stride));
            IntPtr rowDst = (IntPtr)((byte*)bmdDst.Scan0 + (y * bmdDst.Stride));
            CopyMemory(rowDst, rowSrc, (uint)bmdDst.Stride);
        }
    }
    newBitmap.UnlockBits(bmdDst);
    bitmap.UnlockBits(bmdSrc);
    return newBitmap;
}

我几周来一直在研究这个问题,我似乎无法弄清楚这个问题。任何建议都可能有用

0 个答案:

没有答案