using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsAppCache
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            Object lockobject = new Object();

            var t1 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    lock (lockobject)
                    {
                        pb2.Image = Cache.getImageFromCache(number);
                    }
                }
            }, pictureBox1);
            ;


            var t2 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    lock (lockobject)
                    {
                        pb2.Image = Cache.getImageFromCache(number);
                    }
                }
            }, pictureBox2);
            ;

            var t3 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    lock (lockobject)
                    {
                        pb2.Image = Cache.getImageFromCache(number);
                    }
                }
            }, pictureBox3);
            ;

            var t4 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    lock (lockobject)
                    {
                        pb2.Image = Cache.getImageFromCache(number);
                    }
                }
            }, pictureBox4);
            ;


            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();


            Task.WaitAll(t1, t2, t3, t4);
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            ReaderWriterLockSlim rwls = new ReaderWriterLockSlim();

            var t1 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = Cache.getImageFromCache(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox1);
            ;


            var t2 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = Cache.getImageFromCache(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox2);
            ;

            var t3 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = Cache.getImageFromCache(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox3);
            ;

            var t4 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox) pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = Cache.getImageFromCache(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox4);
            ;


            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();


            Task.WaitAll(t1, t2, t3, t4);
        }

        private void Button3_Click(object sender, EventArgs e)
        {


            ReaderWriterLockSlim rwls = new ReaderWriterLockSlim();

            var t1 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox)pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = DB.getImageFromDB(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox1);
            ;


            var t2 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox)pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = DB.getImageFromDB(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox2);
            ;

            var t3 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox)pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = DB.getImageFromDB(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox3);
            ;

            var t4 = new Task((pb) =>
            {
                PictureBox pb2 = (PictureBox)pb;
                while (true)
                {
                    Random ran = new Random();
                    int number = ran.Next(0, 6);
                    rwls.EnterReadLock();
                    pb2.Image = DB.getImageFromDB(number);
                    rwls.ExitReadLock();
                }
            }, pictureBox4);
            ;


            t1.Start();
            t2.Start();
            t3.Start();
            t4.Start();


            Task.WaitAll(t1, t2, t3, t4);



        }
    }


    public static class DB
    {
        public static Bitmap getImageFromDB(int colorNumber)
        {
            Thread.Sleep(1000);

            Color[] color = new Color[7];

            color[0] = Color.White;
            color[1] = Color.Blue;
            color[2] = Color.Green;
            color[3] = Color.Yellow;
            color[4] = Color.Black;
            color[5] = Color.Chocolate;
            color[6] = Color.Brown;




            var b = new Bitmap(1, 1);
            b.SetPixel(0, 0, color[colorNumber]);
            var result = new Bitmap(b, 128, 128);
            return result;
        }
    }


    public static class Cache
    {
        private static List<int> colorCache = new List<int>();
     
        public static Bitmap getImageFromCache(int colorNumber)
        {
            Thread.Sleep(100);
            if (colorCache.Contains(colorNumber))
            {
                Color[] color = new Color[7];

                color[0] = Color.White;
                color[1] = Color.Blue;
                color[2] = Color.Green;
                color[3] = Color.Yellow;
                color[4] = Color.Black;
                color[5] = Color.Chocolate;
                color[6] = Color.Brown;


                var b = new Bitmap(1, 1);
                b.SetPixel(0, 0, color[colorNumber]);
                var result = new Bitmap(b, 128, 128);
                return result;
            }
            else
            {
                colorCache.Add(colorNumber);
                return DB.getImageFromDB(colorNumber);
            }
        }
    }
}