项目场景:
使用多线程访问全局变量,模拟抢票软件
实现过程:
1.num是一个全局任务,开启三个线程同时访问。模拟抢票 。 2.重点在于把总任务在子线程访问的时候先拿一个临时变量先取出来。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;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 总的数量
/// </summary>
public int num = 0;
public int cycle = 0;
public bool Threadflag = false;
/// <summary>
/// 定义一个委托类型
/// </summary>
public delegate void mydelegate1();
/// <summary>
/// 定义一个委托变量
/// </summary>
mydelegate1 MonitorHandle = null;
private void Form1_Load(object sender, EventArgs e)
{
//绑定一个方法给monitorhandle(监控所有线程用)
MonitorHandle = new mydelegate1(MonitorThread);
}
private object oj = new object();
private void test1(object flag)
{
for (int j = 0; j <= cycle; j++)
{
int temp = 0;
try
{
//这里需要访问全局变量,加lock
lock (oj)
{
temp = num;
num--;
}
/* i = num*/
Thread.Sleep(500); ;
if (temp < 1)
{
Threadflag = true;
return;
}
else
{
//BeginInvoke异步方法向textbox里面添加log
this.textBox1.BeginInvoke(new Action(() =>
{
this.textBox1.AppendText("我是Thread:" + flag.ToString() + ">>>" + "剩余票数" + temp.ToString() + Environment.NewLine);
}));
//if (OnUpdataUI != null)
// OnUpdataUI((int)flag, temp);
}
}
catch (Exception e)
{ }
}
}
Thread td1 = null;
Thread td2 = null;
Thread td3 = null;
private void button1_Click(object sender, EventArgs e)
{
Threadflag = false;
num = 10;
cycle = num;
this.button1.Enabled = false;
this.textBox1.Clear();
Thread td = new Thread(ExcuThread);
td.IsBackground = true;
td.Start();
//执行监控方法
if (MonitorHandle != null)
MonitorHandle();
}
private void ExcuThread()
{
td1 = new Thread(test1);
td2 = new Thread(test1);
td3 = new Thread(test1);
td1.Name = "Thread 1";
td2.Name = "Thread 2";
td3.Name = "Thread 3";
td1.IsBackground = true;
td2.IsBackground = true;
td3.IsBackground = true;
td1.Start(1);
td2.Start(2);
td3.Start(3);
}
/// <summary>
/// 监控线程是否结束
/// </summary>
private void MonitorThread()
{
DateTime dt1 = DateTime.Now;
while (true)
{
Application.DoEvents();
//判断当前所有的线程是否停止
if (Threadflag)
{
Threadflag = false;
DateTime dt2 = DateTime.Now;
//计算总的行数和耗时
this.label1.Text = "总行数:" + this.textBox1.Lines.GetUpperBound(0).ToString() + " 耗时:" + ExecDateDiff(dt1, dt2) + "s";
this.button1.Enabled = true;
break;
}
}
}
/// <summary>
/// 计算时间差值
/// </summary>
/// <param name="dateBegin">开始时间</param>
/// <param name="dateEnd">结束时间</param>
/// <returns></returns>
private string ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
{
TimeSpan ts1 = new TimeSpan(dateBegin.Ticks);
TimeSpan ts2 = new TimeSpan(dateEnd.Ticks);
TimeSpan ts3 = ts1.Subtract(ts2).Duration(); //你想转的格式
return (ts3.TotalMilliseconds / 1000).ToString();
}
}
}
感兴趣的同学可以直接复制代码跑跑。