需求:
双色球:投注号码由6个红色球号码和1个蓝色球号码组成。
红色球号码从01--33中选择,不重复
蓝色球号码从01--16中选择
设计逻辑
点击开始按钮:7个球就应该变化
点击开始,都在变化,每一个都相互没有影响,每个球之间没有任何规律
要求每个球的变化:要相互不影响;完全独立---多线程的特点:多线程就是每个线程是完全独立的,相互没有影响的;
开始:
一、多线程完成
1、七个球->7个线程
2、每个线程负责一个球的不断变换
二、如何去变化
1.开启线程
2.在这个线程内部---要在需求指定的球号码所在范围内;取值
3.赋值给球
4.要不断的变化---循环---不断的取值,赋值--(不断的变)
三、重复怎么解决?
1.在赋值的时候,先判断一下,如果重复,再生成一个,重新去赋值;
2.加锁
四、开奖
1.应该让循环变化的球要停止下来
2.把界面上所有的球号码弹出来
代码部分
1、frmSSQ.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StudyThread
{
public partial class FrmSSQ : Form
{
/// <summary>
/// 红球集合
/// </summary>
private string[] RedNums =
{
"01","02","03","04","05","06","07","08","09","10",
"11","12","13","14","15","16","17","18","19","20",
"21","22","23","24","25","26","27","28","29","30",
"31","32","33"
};
/// <summary>
/// 蓝球集合
/// </summary>
private string[] BlueNums =
{
"01","02","03","04","05","06","07","08","09","10",
"11","12","13","14","15","16"
};
private readonly static object _lock = new object();
private bool IsGon = true;
private List<Task> tasks = new List<Task>();
public FrmSSQ()
{
InitializeComponent();
}
private void btnstart_Click(object sender, EventArgs e)
{
// 初始化
tasks = new List<Task>();
this.btnstart.Text = "正在开始...";
this.btnstart.Enabled = false;
this.btnstop.Enabled = true;
// 把7个球都重置为00
this.labelBlue1.Text = "00";
this.labelRed1.Text = "00";
this.labelRed2.Text = "00";
this.labelRed3.Text = "00";
this.labelRed4.Text = "00";
this.labelRed5.Text = "00";
this.labelRed6.Text = "00";
foreach (var control in this.gboSSQ.Controls)
{
if(control is Label)
{
Label label = (Label)control;
tasks.Add(Task.Run(() =>
{
if(label.Name.Contains("Blue")) // 蓝色球
{
// BlueNums中取数据;通过索引来取
//随机的取: 随机的获取索引
while(IsGon)
{
// 索引最大是16
var index = new RandomHelper().GetRandomNumber(0, 16);
string num = BlueNums[index];
this.Invoke(new Action(() =>
{
label.Text = num;
}));
}
}
else // 红色球
{
while(IsGon)
{
// 索引最大是22
var index = new RandomHelper().GetRandomNumber(0, 33);
string num = RedNums[index];
// 赋值之前可以先判断一下,如果有重复的就过去,在循环
// 获取当前界面的所有红色球
lock (_lock)
{
// 获取重复值
var list = this.getCurNums();
if(!list.Contains(num))
{
//只要是判断了,还是会重复
//是在多线程中,委托一个动作让主线程去帮助完成
this.Invoke(new Action(() =>
{
label.Text = num;
}));
}
}
}
}
}));
}
}
// Task.Factory.ContinueWhenAll
创建了一个新任务 continuationTask
。这个新任务在 tasks
数组中的所有任务都完成时执行。
Task.Factory.ContinueWhenAll(tasks.ToArray(), ts =>
{
this.Invoke(new Action(() =>
{
this.showResult();
this.IsGon = true;
this.btnstart.Text = "开始";
this.btnstart.Enabled = true;
this.btnstop.Enabled = false;
}));
});
}
private void btnstop_Click(object sender, EventArgs e)
{
// 停止
this.IsGon = false;
// Task.WaitAll(tasks.ToArray());// 这里会有问题,死锁:主线程和子线程相互等待了: 主线程要等待所有的子线程执行结束;子线程中,赋值问题要交给主线程去完成;形成了相互等待;
//Task.Run(() =>
//{
// Task.WaitAll(tasks.ToArray());
// showResult();
//});
}
private List<string> getCurNums()
{
var list = new List<string>();
foreach (var controls in this.gboSSQ.Controls)
{
if (controls is Label)
{
var label = (Label)controls;
if (label.Name.Contains("Red"))
{
list.Add(label.Text);
}
}
}
return list;
}
/// <summary>
/// 弹框提示数据
/// </summary>
private void showResult()
{
MessageBox.Show(string.Format("本期双色球结果为:{0} {1} {2} {3} {4} {5} 蓝球{6}"
, this.labelRed1.Text
, this.labelRed2.Text
, this.labelRed3.Text
, this.labelRed4.Text
, this.labelRed5.Text
, this.labelRed6.Text
, this.labelBlue1.Text));
}
}
}
2、FrmSSQ.Designer.cs
namespace StudyThread
{
partial class FrmSSQ
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
gboSSQ = new GroupBox();
btnstop = new Button();
btnstart = new Button();
labelBlue1 = new Label();
labelRed6 = new Label();
labelRed5 = new Label();
labelRed4 = new Label();
labelRed3 = new Label();
labelRed2 = new Label();
labelRed1 = new Label();
gboSSQ.SuspendLayout();
SuspendLayout();
//
// gboSSQ
//
gboSSQ.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
gboSSQ.Controls.Add(btnstop);
gboSSQ.Controls.Add(btnstart);
gboSSQ.Controls.Add(labelBlue1);
gboSSQ.Controls.Add(labelRed6);
gboSSQ.Controls.Add(labelRed5);
gboSSQ.Controls.Add(labelRed4);
gboSSQ.Controls.Add(labelRed3);
gboSSQ.Controls.Add(labelRed2);
gboSSQ.Controls.Add(labelRed1);
gboSSQ.Location = new Point(37, 12);
gboSSQ.Name = "gboSSQ";
gboSSQ.Size = new Size(944, 623);
gboSSQ.TabIndex = 0;
gboSSQ.TabStop = false;
gboSSQ.Text = "gboSSQ";
//
// btnstop
//
btnstop.Location = new Point(209, 292);
btnstop.Name = "btnstop";
btnstop.Size = new Size(112, 34);
btnstop.TabIndex = 8;
btnstop.Text = "停止";
btnstop.UseVisualStyleBackColor = true;
btnstop.Click += btnstop_Click;
//
// btnstart
//
btnstart.Location = new Point(6, 292);
btnstart.Name = "btnstart";
btnstart.Size = new Size(112, 34);
btnstart.TabIndex = 7;
btnstart.Text = "开始";
btnstart.UseVisualStyleBackColor = true;
btnstart.Click += btnstart_Click;
//
// labelBlue1
//
labelBlue1.AutoSize = true;
labelBlue1.Location = new Point(17, 128);
labelBlue1.Name = "labelBlue1";
labelBlue1.Size = new Size(32, 24);
labelBlue1.TabIndex = 6;
labelBlue1.Text = "00";
//
// labelRed6
//
labelRed6.AutoSize = true;
labelRed6.Location = new Point(512, 54);
labelRed6.Name = "labelRed6";
labelRed6.Size = new Size(32, 24);
labelRed6.TabIndex = 5;
labelRed6.Text = "00";
//
// labelRed5
//
labelRed5.AutoSize = true;
labelRed5.Location = new Point(414, 54);
labelRed5.Name = "labelRed5";
labelRed5.Size = new Size(32, 24);
labelRed5.TabIndex = 4;
labelRed5.Text = "00";
//
// labelRed4
//
labelRed4.AutoSize = true;
labelRed4.Location = new Point(307, 54);
labelRed4.Name = "labelRed4";
labelRed4.Size = new Size(32, 24);
labelRed4.TabIndex = 3;
labelRed4.Text = "00";
//
// labelRed3
//
labelRed3.AutoSize = true;
labelRed3.Location = new Point(209, 54);
labelRed3.Name = "labelRed3";
labelRed3.Size = new Size(32, 24);
labelRed3.TabIndex = 2;
labelRed3.Text = "00";
//
// labelRed2
//
labelRed2.AutoSize = true;
labelRed2.Location = new Point(115, 54);
labelRed2.Name = "labelRed2";
labelRed2.Size = new Size(32, 24);
labelRed2.TabIndex = 1;
labelRed2.Text = "00";
//
// labelRed1
//
labelRed1.AutoSize = true;
labelRed1.Location = new Point(17, 54);
labelRed1.Name = "labelRed1";
labelRed1.Size = new Size(32, 24);
labelRed1.TabIndex = 0;
labelRed1.Text = "00";
//
// FrmSSQ
//
AutoScaleDimensions = new SizeF(11F, 24F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1015, 647);
Controls.Add(gboSSQ);
Name = "FrmSSQ";
Text = "FrmSSQ";
gboSSQ.ResumeLayout(false);
gboSSQ.PerformLayout();
ResumeLayout(false);
}
#endregion
private GroupBox gboSSQ;
private Label labelRed1;
private Label labelRed2;
private Label labelRed4;
private Label labelRed3;
private Label labelRed6;
private Label labelRed5;
private Label labelBlue1;
private Button btnstart;
private Button btnstop;
}
}
3、RandomHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyThread
{
public class RandomHelper
{
/// <summary>
/// 获取随机数,解决重复问题
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
/// <returns></returns>
public int GetRandomNumber(int min, int max)
{
Guid guid = Guid.NewGuid();//每次都是全新的ID 全球唯一Id
string sGuid = guid.ToString();
int seed = DateTime.Now.Millisecond;
//保证seed 在同一时刻 是不相同的
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 + 3;
break;
default:
seed = seed + 4;
break;
}
}
Random random = new Random(seed);
return random.Next(min, max);
}
}
}