多线程应用——双色球

通过多线程实现双色球选号,

要求:1、红球从01到33不能有重复;2、蓝球从1到16

效果如下:

 

 

 

 

难点:

 

1、多线程实现

 

2、跨线程修改UI

 

3、线程安全(红球不能有重复)

 

4、取消线程

 

5、线程取消导致的死锁

 

代码如下:

 

 

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UnionLotto
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
            
            this.FormClosed += Form1_FormClosed;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Environment.Exit(0);//推出所有进程,防止程序关闭后报错
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            //红球集合
            for (int i = 0; i < redNums.Length; i++)
            {
                redNums[i] = (i + 1).ToString("00");
            }
            //蓝球集合
            for (int i = 0; i < blueNums.Length; i++)
            {
                blueNums[i] = (i + 1).ToString("00");
            }
            this.btnStop.Enabled = false;
        }

        string[] redNums = new string[33];//红色球集合
        string[] blueNums = new string[16];//蓝色球集合
        private static object Lock_object = new object();//线程锁
        CancellationTokenSource cts;
        List<Task> tasks = new List<Task>();

        private void btnStart_Click(object sender, EventArgs e)
        {
            this.btnStart.Text = "运行...";
            this.btnStart.Enabled = false;
            this.btnStop.Enabled = true;
            cts = new CancellationTokenSource();
            //先全部赋值为“00”
            foreach (var item in groupBox1.Controls)
            {
                if (item is Label)
                {
                    Label label = (Label)item;
                    label.Text = "00";
                }
            }

            foreach (var item in groupBox1.Controls)
            {
                if (item is Label)
                {
                    Label label = item as Label;
                    if (label.Name.Contains("Blue"))//蓝球
                    {
                        //1、通过线程获得随机蓝球
                        tasks.Add(Task.Run(() =>
                        {
                            while (!cts.IsCancellationRequested)
                            {
                                //获得随机数
                                int index = RandomHelper.GetRandomNumberDelay(0, 15);
                                //2、跨线程修改UI
                                this.Invoke(new Action(() =>
                                {
                                    label.Text = blueNums[index];

                                }));
                            }

                        }));
                    }
                    else//红球
                    {
                        //1、通过线程获得随机红球
                        tasks.Add(Task.Run(() =>
                        {
                            while (!cts.IsCancellationRequested)
                            {
                                //获得随机数
                                int index = RandomHelper.GetRandomNumberDelay(0, 32);
                                string redNum = redNums[index];
                                lock (Lock_object)//3、线程锁,保证每个线程取值安全
                                {
                                    List<string> redList = GetCurrentRedNumList();
                                    //如果现有label的text中没有与redNum相同的则显示,否则进入下一循环
                                    if (!redList.Contains(redNum))
                                    {
                                        //2、跨线程修改UI
                                        this.Invoke(new Action(() =>
                                        {
                                            label.Text = redNum;
                                        }));
                                    }

                                }

                            }
                        }));
                    }
                }
            }
        }

        //获取红球集合
        private List<string> GetCurrentRedNumList()
        {
            List<string> redNumList = new List<string>();
            foreach (var item in groupBox1.Controls)
            {
                if (item is Label)
                {
                    Label label = item as Label;
                    if (label.Name.Contains("Red"))
                    {
                        redNumList.Add(label.Text);
                    }

                }
            }

            return redNumList;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {

            cts.Cancel();//4、取消线程
            //5、创建子线程来等待所有线程结束,否则将导致死锁
            Task.Run(() =>
            {
                Task.WaitAll(tasks.ToArray());//4、线程取消后,等带所有线程完成
                MessageBox.Show(RedNum1.Text + "," + RedNum2.Text + "," + RedNum3.Text + "," + RedNum4.Text + ","
                    + RedNum5.Text + "," + RedNum6.Text + "," + BlueNum.Text + ",");
                this.Invoke(new Action(() =>
                {
                    this.btnStart.Text = "start";
                    this.btnStart.Enabled = true;
                    this.btnStop.Enabled = false;
                }));
            });


        }
    }
}

 

 

 

 

 代码中获得随机数的方法如下:

using System;
using System.Threading;

namespace UnionLotto
{
    public class RandomHelper
    {
        /// <summary>
        /// new Random().Next(1,100);多线程同时执行结果很高概率相同,
        /// 是用的当前事件为seed,时间相同结果相同
        /// 
        /// 解决随机数重复问题
        /// 同事模拟远程请求的随机延时
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int GetRandomNumberDelay(int min, int max)
        {
            Thread.Sleep(GetRandomNumber(300, 500));
            return GetRandomNumber(min, max);
        }

        public static int GetRandomNumber(int min, int max)
        {
            Guid guid = Guid.NewGuid();
            string sGuid = guid.ToString();
            int seed = DateTime.Now.Millisecond;
            for (int i = 0; i < sGuid.Length; i++)
            {
                switch (sGuid[i])
                {
                    case 'a':
                    case 'b':
                    case 'c':
                    case 'd':
                    case 'e':
                    case 'f':
                    case 'g':
                        seed = seed + 1;
                        break;

                    case 'h':
                    case 'i':
                    case 'j':
                    case 'k':
                    case 'l':
                    case 'm':
                    case 'n':
                        seed = seed + 2;
                        break;

                    case 'o':
                    case 'p':
                    case 'q':
                    case 'r':
                    case 's':
                    case 't':
                        seed = seed + 3;
                        break;

                    case 'u':
                    case 'v':
                    case 'w':
                    case 'x':
                    case 'y':
                    case 'z':
                        seed = seed + 4;
                        break;

                    default:
                        break;
                }
            }
            Random random = new Random(seed);
            return random.Next(min, max);
        }
    }
}

 

posted on 2022-10-25 22:30  hanzq_go  阅读(97)  评论(0编辑  收藏  举报

导航