使用C#中的信号量和缓冲区在线程之间传输图形

时间:2012-03-07 23:55:57

标签: c# multithreading graphics buffer semaphore

我的英语不是很好,写得非常简单,所以提前对不起......

我见过类似的问题,但没有使用图形。

我要做的是设置一个简单的电路显示,其中一个点从ButtonPanel开始,当点击按钮并且绿色时,将释放更多的点,我使用信号量和缓冲区来控制它是否去进入下一个面板,想法是点将围绕面板做一个电路(顺时针运动),直到(现在)硬编码限制使原点停止发出点。

我觉得我对缓冲区和信号量的性质感到困惑,但是就像我对它们所做的那样阅读,我仍然无法让它按照我想要的方式行事......

系统离开第一个面板时,会同时在所有4个WaitPanelThreads中设置一个点,这不是我想要的。

我尝试过添加更多信号量,但这没有任何好处。我构建了自己的信号量和缓冲区,试图了解它们正在做什么,但我无法继续这个程序。我花了很多年的时间试图让系统正常运行,但是我很难过,如果由于我的英语问题而没有多大意义,请问我会更好地说出来。

下面是我为此编写的所有代码,我很确定问题是我构建WaitPanelThreads的地方。任何帮助表示赞赏,我正在尝试自学。

菲利克斯

编辑:我还必须评论下面的代码如果你将它闯入visual studio,那么你可能需要包含两个引用,如果你想看看它是如何设置的话

using System;
using System.Windows.Forms;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Data;
using System.Drawing;

public class Form1 : Form
{

    private Container components = null;
    private ButtonPanelThread p1;
    private Button btn1;
    private WaitPanelThread p2, p3, p4, p5;
    private Thread thread1, thread2, thread3, thread4, thread5;
    private Semaphore semaphore, semaphore1;
    private Buffer buffer, buffer1;
    private Thread semThread, semThread1;
    private Thread buffThread, buffThread1;
    private Panel pnl1, pnl2, pnl3, pnl4, pnl5;


    public Form1()
    {
        InitializeComponent();


        semaphore = new Semaphore();
        semaphore1 = new Semaphore();
        buffer = new Buffer();
        buffer1 = new Buffer();


        p1 = new ButtonPanelThread(new Point(40, 10),
                             30, true, pnl1,
                             Color.Blue,
                             semaphore,
                             buffer,
                             btn1);

        p2 = new WaitPanelThread(new Point(10, 10),
                             80, false, 2, pnl2,
                             Color.White,
                             semaphore,
                             buffer);

        p3 = new WaitPanelThread(new Point(10, 10),
                             77, false, 3, pnl3,
                             Color.White,
                             semaphore,
                             buffer);
        p4 = new WaitPanelThread(new Point(250, 10),
                             77, false, 4, pnl4,
                             Color.White,
                             semaphore,
                             buffer);
        p5 = new WaitPanelThread(new Point(10, 250),
                             77, false, 1, pnl5,
                             Color.White,
                             semaphore,
                             buffer);

        semThread = new Thread(new ThreadStart(semaphore.Start));
        semThread1 = new Thread(new ThreadStart(semaphore1.Start));
        buffThread = new Thread(new ThreadStart(buffer.Start));
        buffThread1 = new Thread(new ThreadStart(buffer1.Start));
        thread1 = new Thread(new ThreadStart(p1.Start));
        thread2 = new Thread(new ThreadStart(p2.Start));
        thread3 = new Thread(new ThreadStart(p3.Start));
        thread4 = new Thread(new ThreadStart(p4.Start));
        thread5 = new Thread(new ThreadStart(p5.Start));


        this.Closing += new CancelEventHandler(this.Form1_Closing);

        semThread.Start();
        semThread1.Start();
        buffThread.Start();
        buffThread1.Start();
        thread1.Start();
        thread2.Start();
        thread3.Start();
        thread4.Start();
        thread5.Start();

    }


    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (components != null)
                components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.Text = "Circuit movements";
        this.Size = new System.Drawing.Size(900, 700);
        this.BackColor = Color.LightGray;

        this.pnl1 = new Panel();
        this.pnl1.Location = new Point(100, 100);
        this.pnl1.Size = new Size(260, 30);
        this.pnl1.BackColor = Color.White;

        this.btn1 = new Button();
        this.btn1.Size = new Size(30, 30);
        this.btn1.BackColor = Color.Pink;
        this.btn1.Location = new System.Drawing.Point(0, 0);


        this.pnl2 = new Panel();
        this.pnl2.Location = new Point(350, 100);
        this.pnl2.Size = new Size(260, 30);
        this.pnl2.BackColor = Color.White;

        this.pnl3 = new Panel();
        this.pnl3.Location = new Point(580, 100);
        this.pnl3.Size = new Size(30, 260);
        this.pnl3.BackColor = Color.White;

        this.pnl4 = new Panel();
        this.pnl4.Location = new Point(350, 360);
        this.pnl4.Size = new Size(260, 30);
        this.pnl4.BackColor = Color.White;

        this.pnl5 = new Panel();
        this.pnl5.Location = new Point(350, 100);
        this.pnl5.Size = new Size(30, 260);
        this.pnl5.BackColor = Color.White;

        this.Controls.Add(pnl1);
        this.Controls.Add(pnl2);
        this.Controls.Add(pnl3);
        this.Controls.Add(pnl4);
        this.Controls.Add(pnl5);
        this.pnl1.Controls.Add(btn1);

        // Wire Closing event.      
        this.Closing += new CancelEventHandler(this.Form1_Closing);
    }

    private void Form1_Closing(object sender, CancelEventArgs e)
    {
        // Environment is a System class.
        // Kill off all threads on exit.
        Environment.Exit(Environment.ExitCode);
    }


}// end class form1


public class Buffer
{
    private Color planeColor;
    private bool empty = true;

    public void Read(ref Color planeColor)
    {
        lock (this)
        {
            // Check whether the buffer is empty.
            if (empty)
                Monitor.Wait(this);
            empty = true;
            planeColor = this.planeColor;
            Monitor.Pulse(this);
        }
    }

    public void Write(Color planeColor)
    {
        lock (this)
        {
            // Check whether the buffer is full.
            if (!empty)
                Monitor.Wait(this);
            empty = false;
            this.planeColor = planeColor;
            Monitor.Pulse(this);
        }
    }

    public void Start()
    {
    }

}// end class Buffer

public class Semaphore
{
    private int count = 0;

    public void Wait()
    {
        lock (this)
        {
            while (count == 0)
                Monitor.Wait(this);
            count = 0;
        }
    }

    public void Signal()
    {
        lock (this)
        {
            count = 1;
            Monitor.Pulse(this);
        }
    }

    public void Start()
    {
    }

}// end class Semaphore

public class ButtonPanelThread
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;
    private Button btn;
    private bool locked = true;



    public ButtonPanelThread(Point origin,
                             int delay,
                             bool westEast,
                             Panel panel,
                             Color colour,
                             Semaphore semaphore,
                             Buffer buffer,
                             Button btn)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? +10 : -10;
        this.yDelta = 0;
        this.semaphore = semaphore;
        this.buffer = buffer;
        this.btn = btn;
        this.btn.Click += new System.
                              EventHandler(this.btn_Click);


    }

    private void btn_Click(object sender,
                           System.EventArgs e)
    {
        locked = !locked;
        this.btn.BackColor = locked ? Color.Pink : Color.LightGreen;
        lock (this)
        {
            if (!locked)
                Monitor.Pulse(this);
        }
    }

    public void Start()
    {
        Color signal = Color.Red;
        Thread.Sleep(delay);


        for (int k = 1; k <= 30; k++)
        {
            this.zeroPlane();
            panel.Invalidate();
            lock (this)
            {
                while (locked)
                {
                    Monitor.Wait(this);
                }
            }
            for (int i = 1; i <= 20; i++)
            {
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);
                panel.Invalidate();
            }
            semaphore.Wait();
            buffer.Write(this.colour);
        }
        this.colour = Color.Gray;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);

        brush.Dispose();    //  Dispose graphics resources. 
        g.Dispose();        //  
    }
}// end class ButtonPanelThread

public class WaitPanelThread
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private int dir;
    /*
     * dir options:
     * 1 - north;
     * 2 - east;
     * 3 - south;
     * 4 - west.
     */
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;


    public WaitPanelThread(Point origin,
                       int delay,
                       bool westEast,
                       int dir,
                       Panel panel,
                       Color colour,
                       Semaphore sem,
                       Buffer buff)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.dir = dir;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);

        switch (dir)
        {
            case 1:
                this.xDelta = 0;
                this.yDelta = -10;
                break;
            case 2:
                this.xDelta = +10;
                this.yDelta = 0;
                break;
            case 3:
                this.xDelta = 0;
                this.yDelta = +10;
                break;
            case 4:
                this.xDelta = -10;
                this.yDelta = 0;
                break;
        }
        this.semaphore = sem;
        this.buffer = buff;

    }

    public void Start()
    {
        this.colour = Color.White;
        for (int k = 1; k <= 40; k++)
        {
            semaphore.Signal();
            this.zeroPlane();

            buffer.Read(ref this.colour);

            for (int i = 1; i <= 20; i++)
            {

                panel.Invalidate();
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);

            }
            this.colour = Color.White;
            panel.Invalidate();


        }
        this.colour = Color.Gray;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        SolidBrush brush = new SolidBrush(colour);
        if (dir == 2 || dir == 4)
        {
            g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        }
        if (dir == 1 || dir == 3)
        {
            g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        }

        brush.Dispose();    //  Dispose graphics resources. 
        g.Dispose();        //  
    }
}// end class WaitPanelThread

public class Driver
{
    public static void Main()//
    {

        Application.Run(new Form1());
    }
}// end class TheOne

0 个答案:

没有答案