多线程实现打字游戏
大家都知道.net中System.Threading命名空间中的Thread类代表了一个线程对象,以创建新的线程,删除、暂停和恢复线程.下面通过一个"打字游戏"的实例来帮助大家了解多线程的机制,直接贴上源代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace game
{
public partial class Form1 : Form
{
//定义委托
public delegate void moving();
//定义线程
private Thread t;
//定义显示字符的标签
private Label label1;
//定义标签里面的内容
string[] matter ={ "A", "B", "C", "D", "E",
"F", "G", "H", "I", "J",
"K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y",
"Z" };
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
//如果标签不为空,就表示窗体上有此标签
if (label1 == null)
{
//无此窗体,新建并初始化
Random r = new Random();
label1 = new System.Windows.Forms.Label();
label1.AutoSize = true;
label1.Name = matter[r.Next(26)];
label1.Text = label1.Name;
label1.Location = new System.Drawing.Point(r.Next(20,this.Size.Width - label1.Size.Width), 0);
//添加到窗体上
this.Controls.Add(label1);
t = new Thread(new ThreadStart(Run)); //创建并启动线程,启动方法为Run,ThreadStart其实是一个委托
t.Start();
}
}
//线程所调用方法,进行标签的移动
private void Run()
{
while (true)
{
//调用移动标签的方法
showLab();
Thread.Sleep(200); //Sleep属性表示将当前线程阻塞指定的毫秒数,就是让线程暂停0.2秒。
}
}
private void showLab()
{
//判断进行控件属性修改的线程是否是创建控件线程外的线程
if (this.InvokeRequired)
{
//让主线程强制执行此方法
moving d = new moving(showLab);
this.Invoke(d,null);
}
else
{
//进行标签的移动
label1.Location = new Point(label1.Location.X, label1.Location.Y + 5);
//如果标签移动到窗体下方的边缘外面,则删除此标签
if (label1.Location.Y >= this.Height - (label1.Size.Height)*4) //(label1.Size.height)*4是标题栏的高度
{
//this.Controls.Remove(label1);
label1 = null;
t.Abort();
}
}
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
//如果用户在键盘上按下标签所表示的字母,则删除此标签
if (e.KeyChar == label1.Name.ToCharArray()[0] || e.KeyChar == label1.Name.ToLower().ToCharArray()[0])
{
this.Controls.Remove(label1);
label1 = null;
t.Abort();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{//如果关闭窗体,强制结束子线程
t.Abort();
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace game
{
public partial class Form1 : Form
{
//定义委托
public delegate void moving();
//定义线程
private Thread t;
//定义显示字符的标签
private Label label1;
//定义标签里面的内容
string[] matter ={ "A", "B", "C", "D", "E",
"F", "G", "H", "I", "J",
"K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y",
"Z" };
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
//如果标签不为空,就表示窗体上有此标签
if (label1 == null)
{
//无此窗体,新建并初始化
Random r = new Random();
label1 = new System.Windows.Forms.Label();
label1.AutoSize = true;
label1.Name = matter[r.Next(26)];
label1.Text = label1.Name;
label1.Location = new System.Drawing.Point(r.Next(20,this.Size.Width - label1.Size.Width), 0);
//添加到窗体上
this.Controls.Add(label1);
t = new Thread(new ThreadStart(Run)); //创建并启动线程,启动方法为Run,ThreadStart其实是一个委托
t.Start();
}
}
//线程所调用方法,进行标签的移动
private void Run()
{
while (true)
{
//调用移动标签的方法
showLab();
Thread.Sleep(200); //Sleep属性表示将当前线程阻塞指定的毫秒数,就是让线程暂停0.2秒。
}
}
private void showLab()
{
//判断进行控件属性修改的线程是否是创建控件线程外的线程
if (this.InvokeRequired)
{
//让主线程强制执行此方法
moving d = new moving(showLab);
this.Invoke(d,null);
}
else
{
//进行标签的移动
label1.Location = new Point(label1.Location.X, label1.Location.Y + 5);
//如果标签移动到窗体下方的边缘外面,则删除此标签
if (label1.Location.Y >= this.Height - (label1.Size.Height)*4) //(label1.Size.height)*4是标题栏的高度
{
//this.Controls.Remove(label1);
label1 = null;
t.Abort();
}
}
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
//如果用户在键盘上按下标签所表示的字母,则删除此标签
if (e.KeyChar == label1.Name.ToCharArray()[0] || e.KeyChar == label1.Name.ToLower().ToCharArray()[0])
{
this.Controls.Remove(label1);
label1 = null;
t.Abort();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{//如果关闭窗体,强制结束子线程
t.Abort();
}
}
}
具体效果如下:
如果你在键盘上按下掉下来的字母,它就会消失.